Программируемое создание и воспроизведение звука через динамики C ++ - PullRequest
4 голосов
/ 20 сентября 2009

Я делаю игру на родном vc ++ (не .Net)

Я ищу способ воспроизвести шум (может быть, 8-битный или что-то) через настоящие динамики (не внутренние). Я знаю о PlaySound, но я не хочу делать мой EXE большой. Я хочу запрограммировать звук.

Есть ли способ API (вроде Beep ()), но который воспроизводится через настоящие динамики?

Спасибо

Ответы [ 4 ]

11 голосов
/ 20 сентября 2009

Вы упоминаете, что знаете о PlaySound. Один из его флагов (SND_MEMORY) позволит вам воспроизвести WAVE, который уже загружен в память, то есть буфер, который вы создали сами. Пока в буфере есть соответствующий заголовок WAVE, все, что вы вставляете туда, должно воспроизводиться через динамики.

Заголовок является 44-байтовым блоком, который является довольно прямым

struct WaveHeader
{
    DWORD chunkID;       // 0x46464952 "RIFF" in little endian
    DWORD chunkSize;     // 4 + (8 + subChunk1Size) + (8 + subChunk2Size)
    DWORD format;        // 0x45564157 "WAVE" in little endian

    DWORD subChunk1ID;   // 0x20746d66 "fmt " in little endian
    DWORD subChunk1Size; // 16 for PCM
    WORD  audioFormat;   // 1 for PCM, 3 fot EEE floating point , 7 for μ-law
    WORD  numChannels;   // 1 for mono, 2 for stereo
    DWORD sampleRate;    // 8000, 22050, 44100, etc...
    DWORD byteRate;      // sampleRate * numChannels * bitsPerSample/8
    WORD  blockAlign;    // numChannels * bitsPerSample/8
    WORD  bitsPerSample; // number of bits (8 for 8 bits, etc...)

    DWORD subChunk2ID;   // 0x61746164 "data" in little endian
    DWORD subChunk2Size; // numSamples * numChannels * bitsPerSample/8 (this is the actual data size in bytes)
};

Вы бы настроили свой буфер с чем-то похожим на:

char *myBuffer = new char[sizeof(WaveHeader) + myDataSize];

WaveHeader *header = (WaveHeader*)myBuffer;
// fill out the header...

char *data = myBuffer + sizeof(WaveHeader); //jumps to beginning of data
// fill out waveform data...

Итак, вы используете что-то вроде:

PlaySound(myBuffer, NULL, SND_MEMORY | SND_ASYNC);

Я предполагаю, что вы будете использовать сгенерированный звук на протяжении всего срока службы вашего приложения. Если нет, будьте осторожны с этим SND_ASYNC флагом. То есть не освобождайте буфер сразу после вызова PlaySound (пока он еще используется).

Документы MSDN PlaySound
Страница с более подробной информацией о заголовке WAV ( OLD - сейчас не работает)

DirectX также поддерживает воспроизведение звука из буферов в памяти и является гораздо более мощным API, но, возможно, излишним для того, что вам нужно сделать:)

1 голос
/ 20 сентября 2009

Хотя в Windows есть несколько возможностей, одним из самых простых является sndPlaySound ():

  • включает mmsystem.h
  • ссылка на winmm.lib
  • ::sndPlaySound("sound.wav", SND_ASYNC|SND_NODEFAULT);
  • для остановки воспроизведения: ::sndPlaySound(NULL, NULL);

Конечно, есть и другие способы, такие как mci и прямой звук, которые могут лучше удовлетворить ваши потребности, если вы будете более четко видеть, что вам нужно.

0 голосов
/ 20 сентября 2009

Мой ответ на другой вопрос может быть полезным, проверьте его здесь

Я говорю о простом в использовании API с открытым исходным кодом ( Synthesis Toolkit ), который имеет классы для чтения / записи wav-файлов и имеет простые в использовании классы-обертки для вывода в реальном времени различных драйверов (wdm, Асио, Джек, ...)

Имхо проще в использовании, чем функции winapi

0 голосов
/ 20 сентября 2009

Я нашел это: http://www.xtremevbtalk.com/showthread.php?p=829281 это может вам пригодиться

...