728x90

C#에서 피아노 소리를 생성하거나 재생하는 방법을 살펴보겠습니다. C#에서도 다양한 접근 방식이 있으며, 아래에서 설명할 방법들은 MIDI 파일 사용, WAV 파일 사용, 그리고 NAudio와 같은 라이브러리를 사용한 실시간 오디오 생성입니다.

1. MIDI 파일로 피아노 소리 내기

MIDI 파일을 생성하거나 재생하여 피아노 소리를 내는 방법을 설명합니다. MIDI 파일은 악기 소리와 음계 정보를 포함하고 있어 피아노 소리를 포함할 수 있습니다.

1.1. MIDI 파일 생성

MIDI 파일 생성에는 NAudio 라이브러리를 사용할 수 있습니다.

  1. NAudio 설치: NuGet 패키지 관리자에서 NAudio 패키지를 설치합니다.

    Install-Package NAudio
  2. MIDI 파일 생성 코드

    using NAudio.Midi;
    using System;
    
    class Program
    {
        static void Main(string[] args)
        {
            CreatePianoMidi("piano.mid");
        }
    
        static void CreatePianoMidi(string filePath)
        {
            var midiFile = new MidiFile();
            var track = new MidiTrack();
            midiFile.Tracks.Add(track);
    
            // 피아노 소리 (MIDI 채널 1)
            // 피아노 음계 C4 (노트 번호 60)
            track.Events.Add(new NoteOnEvent(0, 1, 60, 100));
            track.Events.Add(new NoteOffEvent(500, 1, 60, 0));
    
            // MIDI 파일 저장
            midiFile.Save(filePath);
        }
    }

1.2. MIDI 파일 재생

MIDI 파일을 재생하기 위해 Windows API를 사용하여 재생할 수 있습니다.

using System;
using System.Runtime.InteropServices;
using System.Text;

class Program
{
    [DllImport("winmm.dll", CharSet = CharSet.Auto)]
    private static extern int mciSendString(string command, StringBuilder returnValue, int returnLength, IntPtr hwndCallback);

    static void Main(string[] args)
    {
        PlayMidi("piano.mid");
        Console.WriteLine("Press any key to stop...");
        Console.ReadKey();
        StopMidi();
    }

    static void PlayMidi(string filePath)
    {
        string command = $"open \"{filePath}\" type sequencer alias midi";
        mciSendString(command, null, 0, IntPtr.Zero);

        command = "play midi";
        mciSendString(command, null, 0, IntPtr.Zero);
    }

    static void StopMidi()
    {
        string command = "stop midi";
        mciSendString(command, null, 0, IntPtr.Zero);

        command = "close midi";
        mciSendString(command, null, 0, IntPtr.Zero);
    }
}

2. WAV 파일로 피아노 소리 내기

WAV 파일을 생성하고 이를 재생하여 피아노 소리를 내는 방법입니다.

2.1. WAV 파일 생성

피아노 음계의 WAV 파일을 생성하는 방법입니다.

using System;
using System.IO;
using System.Math;

class Program
{
    static void Main(string[] args)
    {
        CreatePianoWaveFile("piano.wav", 261.63, 1.0); // C4 음계, 1초 길이
    }

    static void CreatePianoWaveFile(string filePath, double frequency, double duration)
    {
        int sampleRate = 44100;
        short amplitude = 32760;
        int numSamples = (int)(sampleRate * duration);
        byte[] waveData = new byte[numSamples * 2];

        // WAV 헤더
        byte[] header = new byte[44];
        int fileSize = 36 + numSamples * 2;
        int byteRate = sampleRate * 2;

        // RIFF 헤더
        Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes("RIFF"), 0, header, 0, 4);
        Buffer.BlockCopy(BitConverter.GetBytes(fileSize), 0, header, 4, 4);
        Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes("WAVE"), 0, header, 8, 4);

        // fmt 청크
        Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes("fmt "), 0, header, 12, 4);
        Buffer.BlockCopy(BitConverter.GetBytes(16), 0, header, 16, 4);
        Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, header, 20, 2); // PCM 형식
        Buffer.BlockCopy(BitConverter.GetBytes((short)1), 0, header, 22, 2); // 모노
        Buffer.BlockCopy(BitConverter.GetBytes(sampleRate), 0, header, 24, 4);
        Buffer.BlockCopy(BitConverter.GetBytes(byteRate), 0, header, 28, 4);
        Buffer.BlockCopy(BitConverter.GetBytes((short)2), 0, header, 32, 2); // 블록 정렬
        Buffer.BlockCopy(BitConverter.GetBytes((short)16), 0, header, 34, 2); // 비트 깊이

        // data 청크
        Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes("data"), 0, header, 36, 4);
        Buffer.BlockCopy(BitConverter.GetBytes(numSamples * 2), 0, header, 40, 4);

        // WAV 데이터 생성
        for (int i = 0; i < numSamples; i++)
        {
            short sample = (short)(amplitude * Sin(2 * PI * frequency * i / sampleRate));
            Buffer.BlockCopy(BitConverter.GetBytes(sample), 0, waveData, i * 2, 2);
        }

        // 파일 쓰기
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            fs.Write(header, 0, header.Length);
            fs.Write(waveData, 0, waveData.Length);
        }
    }
}

2.2. WAV 파일 재생

WAV 파일을 재생하기 위해 System.Media.SoundPlayer 클래스를 사용할 수 있습니다.

using System.Media;

class Program
{
    static void Main(string[] args)
    {
        PlayWaveFile("piano.wav");
    }

    static void PlayWaveFile(string filePath)
    {
        using (SoundPlayer player = new SoundPlayer(filePath))
        {
            player.PlaySync(); // 파일 재생이 완료될 때까지 대기
        }
    }
}

3. 실시간 피아노 소리 생성

NAudio와 같은 라이브러리를 사용하면 실시간으로 피아노 소리를 생성하고 재생할 수 있습니다.

3.1. NAudio를 사용한 피아노 소리 생성 및 재생

  1. NAudio 설치: NuGet 패키지 관리자에서 NAudio 패키지를 설치합니다.

    Install-Package NAudio
  2. 피아노 소리 생성 및 재생 코드

    using NAudio.Wave;
    using NAudio.Wave.SampleProviders;
    using System;
    
    class Program
    {
        static void Main(string[] args)
        {
            PlayPianoSound("C4", 1.0); // C4 음계, 1초 길이
        }
    
        static void PlayPianoSound(string note, double duration)
        {
            int sampleRate = 44100;
            float amplitude = 0.25f;
            float frequency = GetPianoFrequency(note);
            var waveProvider = new SignalGenerator(sampleRate, 1)
            {
                Frequency = frequency,
                Amplitude = amplitude,
                WaveShape = SignalGenerator.WaveShape.Sine
            };
    
            using (var waveOut = new WaveOutEvent())
            {
                waveOut.Init(waveProvider);
                waveOut.Play();
                System.Threading.Thread.Sleep((int)(duration * 1000));
                waveOut.Stop();
            }
        }
    
        static float GetPianoFrequency(string note)
        {
            return note switch
            {
                "C4" => 261.63f,
                "D4" => 293.66f,
                "E4" => 329.63f,
                "F4" => 349.23f,
                "G4" => 392.00f,
                "A4" => 440.00f,
                "B4" => 493.88f,
                _ => throw new ArgumentException("Invalid note")
            };
        }
    }

코드 설명

  • SignalGenerator: 사인파를 생성하는 클래스입니다.
  • WaveOutEvent: 오디오 출력을 관리합니다.
  • PlayPianoSound: 지정된 피아노 음계와 길이로 사운드를 생성하고 재생합니다.

결론

C#에서 피아노 소리를 생성하고 재생하는 방법은 MIDI 파일을 사용하거나 WAV 파일로 저장하거나, NAudio와 같은 라이브러리를 사용하여 실시간으로 소리를 생성할 수 있습니다. 각 방법은 사용자의 필요에 따라 적절하게 선택할 수 있습니다.

728x90
반응형

'Software > C#' 카테고리의 다른 글

C# 시작하기 - http 쿠키  (0) 2024.08.17
C# 시작하기 - 멀티스레드  (0) 2024.08.17
C# 시작하기 - WebSocket  (0) 2024.07.28
MAUI 시작하기 - HttpClient 및 WebSocket  (0) 2024.07.28
MAUI 시작하기 - 숫자맞추기  (0) 2024.07.28

+ Recent posts