Использование waveOutWrite с динамически распределенной памятью - PullRequest
0 голосов
/ 10 февраля 2019

Я экспериментировал со звуком, используя C.

Я нашел фрагмент кода, который позволил бы мне генерировать звуковой сигнал PCM и выводить его через звуковую карту.

Это сработалодовольно хорошо для того, что это было.

Вот код, который работает: (Вы должны связать winmm, чтобы это работало)
(ВНИМАНИЕ: Это довольно громко.)

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>

//#pragma comment(lib, "winmm.lib")

int main()
{
    HWAVEOUT hWaveOut=0;
    WAVEFORMATEX wfx = {WAVE_FORMAT_PCM,1,8000,8000,1,8,0};
    //buffer to hold 1 minute of pcm wave data (8 bit, 8khz sample rate)
    char buffer[8000*60];
    int i;
    for (i=0;i<8000*60;i++){
        //generate pseudo-random sound.
        buffer[i] = (i*5&(i>>7)|i*3&(i*4>>10));
    }
    waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
    WAVEHDR header = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
    waveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &header, sizeof(WAVEHDR));
    Sleep(60*1000);
    waveOutUnprepareHeader(hWaveOut, &header, sizeof(WAVEHDR));
    waveOutClose(hWaveOut);
    return 0;
}

Тем не менее, я хотел проанализировать и воспроизвести файлы .wav, используя аналогичный метод.

Я понял, что, хотя приведенный выше код работает (где статически размещается буфер) Тем не менее, когда я выделяю память динамически (используя mallocнапример), нет воспроизводимого звука.Я слышу очень хриплый гудящий звук, который указывает, что была выполнена функция waveOutWrite(), но нет другого воспроизводимого звука.

Вот пример, который не работает:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>

//#pragma comment(lib, "winmm.lib")

int main()
{
    HWAVEOUT hWaveOut=0;
    WAVEFORMATEX wfx = {WAVE_FORMAT_PCM,1,8000,8000,1,8,0};
    //buffer to hold 1 minute of pcm wave data (8 bit, 8khz sample rate)
    char *buffer = malloc(sizeof(char)*8000*60);
    int i;
    for (i=0;i<8000*60;i++){
        //generate pseudo-random sound.
        buffer[i] = (i*5&(i>>7)|i*3&(i*4>>10));
    }
    waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
    WAVEHDR header = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
    waveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR));
    waveOutWrite(hWaveOut, &header, sizeof(WAVEHDR));
    Sleep(60*1000);
    waveOutUnprepareHeader(hWaveOut, &header, sizeof(WAVEHDR));
    waveOutClose(hWaveOut);
    return 0;
}

Примечание: я слышал, что есть способ «заблокировать» часть памяти, и я мог бы использовать это для воспроизведения аудио-буфера, который был динамически распределен.Если так, то как бы я это сделал?

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

Большое спасибо за потраченное время!Вы, люди, потрясающие.

Обновление:

Я обнаружил, что документация Microsoft использует функции GlobalAlloc(), HeapAlloc(), LocalAlloc() и VirtualAlloc() для выделения памяти для волновых буферов.Код ниже взят из этого примера :

char *buffer = LocalAlloc(LMEM_FIXED,8000*60); //Doesn't work. Still no sound.

Это также взято из другого примера :

HANDLE hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, 8000*60);
char *buffer = GlobalLock(hData); //Also doesn't work, no sound.

1 Ответ

0 голосов
/ 12 февраля 2019

Проблема здесь:

WAVEHDR header = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };

Здесь sizeof(buffer) - это размер указателя на буфер, потому что буфер - это char *.В вашем первом примере буфер был массивом char, поэтому sizeof(buffer) возвращал размер буфера.

Вы должны предоставить выделенный размер, который вы вычислили выше.Я бы использовал пару констант или переменных, чтобы отслеживать размер, чтобы вы не повторяли вычисления.Например:

//buffer to hold 1 minute of pcm wave data (8 bit, 8khz sample rate)
const size_t samples_per_second = 8000;
const size_t seconds = 60;
const size_t size = samples_per_second * seconds;
unsigned char *buffer = malloc(size);
size_t i;
for (i=0;i<size;i++){
    //generate pseudo-random sound.
    buffer[i] = (i*5&(i>>7)|i*3&(i*4>>10));
}
waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
WAVEHDR header = { buffer, size, 0, 0, 0, 0, 0, 0 };

Возможно, вы захотите использовать unsigned char для своих образцов.Я считаю, что форматы WAV хотят беззнаковые значения для 8-битных семплов.(Для других размеров вы хотите подписать образцы.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...