Как сделать вторичный звук DirectBuffer?

0

Я пытаюсь получить звук с простой клавиатуры. Похож на маленькую драм-машину. Если 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);

Но нет звука, скажите, что не правильно в моем коде или, может быть, во всей концепции. Спасибо.

  • 0
    Эй, пожалуйста, помогите мне
Теги:

1 ответ

0
Лучший ответ

Когда вы инициализируете WAVEFORMATEX, вы забываете установить член nAvgBytesPerSec. Добавьте эту строку после инициализации wvFormat.nBlockAlign:

wvFormat.nAvgBytesPerSec = wvFormat.nSamplesPerSec * wvFormat.nBlockAlign;

Кроме того, я подозреваю, что это может быть проблемой:

kickbuf->SetVolume(-2500);

Я подозреваю, что это просто затмит ваш образец на абсолютную тишину. Попробуйте принять вызов, чтобы он воспроизводился на полном объеме.

Но, скорее всего, ни один из приведенных выше примеров кода не показывает валидацию возвращаемых значений из любого из API DirectSound и ни одно из значений ввода-вывода файла. Вы подтвердили, что HRESULT, возвращенные всеми DSound API, возвращают S_OK? Пробовали ли вы печатать или используете OutputDebugString для печати значений, вычисленных для членов WAVEFORMATEX?
Отлаживаете ли вы переадресацию вызовов для проверки того, что вы получаете достоверные данные в своих буферах?

Надеюсь это поможет.

  • 0
    Да, но не заметил ArgBytesPerSec, спасибо, если это поможет, я буду благодарен.
  • 0
    Я подозреваю, что CreateSoundBuffer завершился ошибкой из-за неправильной инициализации WAVEFORMATEX.
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню