Звуковые данные IAudioCaptureClient (WASAPI)
От: ArtyomR0Bot  
Дата: 19.08.13 09:06
Оценка:
Здравствуйте.
В Windows Vista/7 нужно иногда захватывать небольшой кусок звука и анализировать его. Позже я хочу переделать захват звука с устройства воспроизведения, а не захвата. Но пока есть другие вопросы.
Будьте добры, подскажите, правильно ли я делаю, и намекните, каков формат данных в звуковом буфере.
В этом тестовом примере я сделал как знаю, но почему-то при выбранном микрофоне в качестве устройства записи по-умолчанию когда он отключен необычно большие значения получаются.

#include <Windows.h>
#include <Mmdeviceapi.h>
#include <Audioclient.h>
#include <Strsafe.h>
#include <stdio.h>


const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);


int main(void)
{
    HRESULT hr;
    IMMDeviceEnumerator *pEnumerator = NULL;
    IMMDevice *pDevice = NULL;
    IAudioClient *pAudioClient = NULL;
    WAVEFORMATEX *pwfx = NULL;
    UINT32 bufferFrameCount;
    IAudioCaptureClient *pCaptureClient = NULL;
    UINT32 packetLength;
    BYTE *pData;
    UINT32 numFramesAvailable;
    DWORD flags;
    UINT32 i;
    
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    
    hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL,
                          CLSCTX_ALL, IID_IMMDeviceEnumerator,
                          (void**)&pEnumerator);
    
    hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole,
                                              &pDevice);
    
    hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL,
                           NULL, (void**)&pAudioClient);
    
    hr = pAudioClient->GetMixFormat(&pwfx);
    
    printf("Channels: %d\n"
           "Sample rate: %d\n"
           "Bytes rate: %d\n"
           "Block align: %d\n"
           "Bits per sample: %d\n",
           pwfx->nChannels,
           pwfx->nSamplesPerSec,
           pwfx->nAvgBytesPerSec,
           pwfx->nBlockAlign,
           pwfx->wBitsPerSample);
    
    hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0,
                                  0, 0, pwfx, NULL);
    
    hr = pAudioClient->GetBufferSize(&bufferFrameCount);
    
    hr = pAudioClient->GetService(IID_IAudioCaptureClient,
                                  (void**)&pCaptureClient);
    
    hr = pAudioClient->Start();
    
    do
    {
        do
        {
            Sleep(100);
            hr = pCaptureClient->GetNextPacketSize(&packetLength);
        }
        while (packetLength == 0);
        
        hr = pCaptureClient->GetBuffer(&pData,
                                       &numFramesAvailable,
                                       &flags, NULL, NULL);
        
        hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
    }
    while (flags & AUDCLNT_BUFFERFLAGS_SILENT);
    
    if (pwfx->nChannels == 2 && pwfx->wBitsPerSample == 32)
    {
        for (i = 0; i < numFramesAvailable; i += 2)
        {
            printf("%15u %15u\n",
                   ((UWORD*)pData)[i],
                   ((UWORD*)pData)[i + 1]);
        }
    }
    
    hr = pAudioClient->Stop();
    
    return 0;
}


Выводится следующее:

Channels: 2
Sample rate: 44100
Bytes rate: 352800
Block align: 8
Bits per sample: 32
              0               0
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0               0
              0           47104
              0           47104
              0           47104
[..]
              0           47104
              0               0
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
              0           47104
iaudiocaptureclient wasapi core audio apis
Re: Звуковые данные IAudioCaptureClient (WASAPI)
От: ArtyomR0Bot  
Дата: 19.08.13 10:15
Оценка:
Заметил ошибку, из-за которой выводится только половина.

for (i = 0; i < numFramesAvailable; i += 2)
{
    printf("%15u %15u\n",
           ((UWORD*)pData)[i],
           ((UWORD*)pData)[i + 1]);
}


Должно быть:

    printf("%15u %15u\n",
           ((WORD*)&((DWORD*)pData)[i])[0],
           ((WORD*)&((DWORD*)pData)[i])[1]);
Re[2]: Звуковые данные IAudioCaptureClient (WASAPI)
От: ArtyomR0Bot  
Дата: 19.08.13 10:19
Оценка:
Цикл должен быть таким:
        for (i = 0; i < numFramesAvailable; i++)
        {
            printf("%15u %15u\n",
                   ((WORD*)&((DWORD*)pData)[i])[0],
                   ((WORD*)&((DWORD*)pData)[i])[1]);
        }
Re: Звуковые данные IAudioCaptureClient (WASAPI)
От: ArtyomR0Bot  
Дата: 19.08.13 17:06
Оценка:
Всё, я разобрался. На самом деле там данные типа float. Например, если размер пакета возвращает 441, и там 2 канала, значит там будет 882 семпла, левый и правый чередуются. Такой код выдаёт правдоподобный результат для синусоиды в одном канале:

    do
    {
        Sleep(10);
        
        hr = pCaptureClient->GetNextPacketSize(&packetLength);
        
        if (packetLength != 0)
        {
            hr = pCaptureClient->GetBuffer(&pData,
                                           &numFramesAvailable,
                                           &flags, NULL, NULL);
            
            if (!(flags & AUDCLNT_BUFFERFLAGS_SILENT))
            {
                printf("Packet size: %d\n", packetLength);
                
                if (pwfx->nChannels == 2 && pwfx->wBitsPerSample == 32)
                {
                    for (i = 0; i < numFramesAvailable * 2; i+=2)
                    {
                        CopyMemory(&f[0], &((float*)pData)[i], sizeof(float));
                        CopyMemory(&f[1], &((float*)pData)[i+1], sizeof(float));
                        //printf("%8d %7.4f %7.4f\n", i, f[0], f[1]);
                    }
                }
            }
            
            hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
        }
    }
    while (1);
Re[2]: Звуковые данные IAudioCaptureClient (WASAPI)
От: CyberDemon Россия  
Дата: 22.08.13 07:47
Оценка:
Здравствуйте, ArtyomR0Bot, Вы писали:

ARB>Всё, я разобрался. На самом деле там данные типа float. Например, если размер пакета возвращает 441, и там 2 канала, значит там будет 882 семпла, левый и правый чередуются. Такой код выдаёт правдоподобный результат для синусоиды в одном канале:


Кстати, что там float, "русским" языком написано в формате. Кейворд — WAVEFORMATEXTENSIBLE
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.