Я пытаюсь получить звук с простой клавиатуры. Похож на маленькую драм-машину. Если DirectSound не подходит для этого, предложите что-нибудь еще. В моем коде я не знаю, что случилось. Здесь он без проверки ошибок и с переводами:
//Declaring the IDirectSound object
IDirectSound* device;
DirectSoundCreate(NULL, &device, NULL);
device->SetCooperativeLevel(hWnd, DSSCL_NORMAL );
/* Declaring secondary buffers */
IDirectSoundBuffer* kickbuf;
IDirectSoundBuffer* snarebuf;
/* Declaring .wav files pointers
And to structures for reading the information int the begining of the .wav file */
FILE* fkick;
FILE* fsnare;
sWaveHeader kickHdr;
sWaveHeader snareHdr;
Структура sWaveHeader объявляется следующим образом:
typedef struct sWaveHeader
{
char RiffSig[4]; // 'RIFF'
unsigned long WaveformChunkSize; // 8
char WaveSig[4]; // 'WAVE'
char FormatSig[4]; // 'fmt '
unsigned long FormatChunkSize; // 16
unsigned short FormatTag; // WAVE_FORMAT_PCM
unsigned short Channels; // Channels
unsigned long SampleRate;
unsigned long BytesPerSec;
unsigned short BlockAlign;
unsigned short BitsPerSample;
char DataSig[4]; // 'data'
unsigned long DataSize;
} sWaveHeader;
Открытие файла.wav
#define KICK "D:/muzic/kick.wav"
#define SNARE "D:/muzic/snare.wav"
fkick = fopen(KICK, "rb")
fsnare = fopen(SNARE, "rb")
Здесь я делаю функцию, которая выполняет общую работу для snarebuf * и ** kickbuf
int read_wav_to_WaveHeader (sWaveHeader* , FILE* , IDirectSoundBuffer* ); // The declaring
Но я не буду писать эту функцию, просто покажу, как она работает с kickbuf, например.
fseek(fkick, 0, SEEK_SET); // Zero the position in file
fread(&kickHdr, 1, sizeof(sWaveHeader), fkick); // reading the sWaveHeader structure from file
Здесь идет проверка на соответствие, если структура sWaveHeader:
if(memcmp(pwvHdr.RiffSig, "RIFF", 4) ||
memcmp(pwvHdr.WaveSig, "WAVE", 4) ||
memcmp(pwvHdr.FormatSig, "fmt ", 4) ||
memcmp(pwvHdr.DataSig, "data", 4))
return 1;
Объявление формата и дескриптора для буфера и их заполнение:
DSBUFFERDESC bufDesc;
WAVEFORMATEX wvFormat;
ZeroMemory(&wvFormat, sizeof(WAVEFORMATEX));
wvFormat.wFormatTag = WAVE_FORMAT_PCM;
wvFormat.nChannels = kickHdr.Channels;
wvFormat.nSamplesPerSec = kickHdr.SampleRate;
wvFormat.wBitsPerSample = kickHdr.BitsPerSample;
wvFormat.nBlockAlign = wvFormat.wBitsPerSample / 8 * wvFormat.nChannels;
ZeroMemory(&bufDesc, sizeof(DSBUFFERDESC));
bufDesc.dwSize = sizeof(DSBUFFERDESC);
bufDesc.dwFlags = DSBCAPS_CTRLVOLUME |
DSBCAPS_CTRLPAN |
DSBCAPS_CTRLFREQUENCY;
bufDesc.dwBufferBytes = kickHdr.DataSize;
bufDesc.lpwfxFormat = &wvFormat;
Ну, создание буфера:
device->CreateSoundBuffer(&bufDesc, &kickbuf, NULL); // Any mistakes by this point?
Теперь блокируем буфер и загружаем в него некоторые данные. Эти данные начинаются после байтов sizeof (sWaveHeader) в WAVE файле, не так ли?
LPVOID Ptr1; // pointer on a pointer on a First block of data
LPVOID Ptr2; // pointer on a pointer on a Second block of data
DWORD Size1, Size2; // their sizes
Теперь вызов метода Lock():
kickbuf->Lock((DWORD)LockPos, (DWORD)Size,
&Ptr1, &Size1,
&Ptr2, &Size2, 0);
Загрузка данных (это нормально?):
fseek(fkick, sizeof(sWaveHeader), SEEK_SET);
fread(Ptr1, 1, Size1, fkick);
if(Ptr2 != NULL)
fread(Ptr2, 1, Size2, fkick);
Разблокировка буфера:
kickbuf->Unlock(Ptr1, Size1, Ptr2, Size2);
Установка громкости:
kickbuf->SetVolume(-2500);
Затем я делаю цикл (1): 1. запросите нажатие клавиши 2. если она нажата:
kickbuf->SetCurrentPosition(0)
kickbuf->Play(0,0,0);
Но нет звука, скажите, что не правильно в моем коде или, может быть, во всей концепции. Спасибо.
Когда вы инициализируете WAVEFORMATEX, вы забываете установить член nAvgBytesPerSec. Добавьте эту строку после инициализации wvFormat.nBlockAlign:
wvFormat.nAvgBytesPerSec = wvFormat.nSamplesPerSec * wvFormat.nBlockAlign;
Кроме того, я подозреваю, что это может быть проблемой:
kickbuf->SetVolume(-2500);
Я подозреваю, что это просто затмит ваш образец на абсолютную тишину. Попробуйте принять вызов, чтобы он воспроизводился на полном объеме.
Но, скорее всего, ни один из приведенных выше примеров кода не показывает валидацию возвращаемых значений из любого из API DirectSound и ни одно из значений ввода-вывода файла. Вы подтвердили, что HRESULT, возвращенные всеми DSound API, возвращают S_OK? Пробовали ли вы печатать или используете OutputDebugString для печати значений, вычисленных для членов WAVEFORMATEX?
Отлаживаете ли вы переадресацию вызовов для проверки того, что вы получаете достоверные данные в своих буферах?
Надеюсь это поможет.