如何在WASAPICaptureSharedEventDriven中以原始格式保存音频文件

uan

我想从麦克风录制音频并将数据保存为原始格式,然后找到WASAPICaptureSharedEventDriven。此示例应用程序使用Core Audio API从用户指定的输入设备捕获音频数据并将其写入wav文件。这是代码:

//  WAV file writer.
//
//  This is a VERY simple .WAV file writer.
//

//
//  A wave file consists of:
//
//  RIFF header:    8 bytes consisting of the signature "RIFF" followed by a 4 byte file length.
//  WAVE header:    4 bytes consisting of the signature "WAVE".
//  fmt header:     4 bytes consisting of the signature "fmt " followed by a WAVEFORMATEX 
//  WAVEFORMAT:     <n> bytes containing a waveformat structure.
//  DATA header:    8 bytes consisting of the signature "data" followed by a 4 byte file length.
//  wave data:      <m> bytes containing wave data.
//
//
//  Header for a WAV file - we define a structure describing the first few fields in the header for convenience.
//
struct WAVEHEADER
{
    DWORD   dwRiff;                     // "RIFF"
    DWORD   dwSize;                     // Size
    DWORD   dwWave;                     // "WAVE"
    DWORD   dwFmt;                      // "fmt "
    DWORD   dwFmtSize;                  // Wave Format Size
};

//  Static RIFF header, we'll append the format to it.
const BYTE WaveHeader[] = 
{
    'R',   'I',   'F',   'F',  0x00,  0x00,  0x00,  0x00, 'W',   'A',   'V',   'E',   'f',   'm',   't',   ' ', 0x00, 0x00, 0x00, 0x00
};

//  Static wave DATA tag.
const BYTE WaveData[] = { 'd', 'a', 't', 'a'};

//
//  Write the contents of a WAV file.  We take as input the data to write and the format of that data.
//
bool WriteWaveFile(HANDLE FileHandle, const BYTE *Buffer, const size_t BufferSize, const WAVEFORMATEX *WaveFormat)
{
    DWORD waveFileSize = sizeof(WAVEHEADER) + sizeof(WAVEFORMATEX) + WaveFormat->cbSize + sizeof(WaveData) + sizeof(DWORD) + static_cast<DWORD>(BufferSize);
    BYTE *waveFileData = new (std::nothrow) BYTE[waveFileSize];
    BYTE *waveFilePointer = waveFileData;
    WAVEHEADER *waveHeader = reinterpret_cast<WAVEHEADER *>(waveFileData);

    if (waveFileData == NULL)
    {
        printf("Unable to allocate %d bytes to hold output wave data\n", waveFileSize);
        return false;
    }

    //
    //  Copy in the wave header - we'll fix up the lengths later.
    //
    CopyMemory(waveFilePointer, WaveHeader, sizeof(WaveHeader));
    waveFilePointer += sizeof(WaveHeader);

    //
    //  Update the sizes in the header.
    //
    waveHeader->dwSize = waveFileSize - (2 * sizeof(DWORD));
    waveHeader->dwFmtSize = sizeof(WAVEFORMATEX) + WaveFormat->cbSize;

    //
    //  Next copy in the WaveFormatex structure.
    //
    CopyMemory(waveFilePointer, WaveFormat, sizeof(WAVEFORMATEX) + WaveFormat->cbSize);
    waveFilePointer += sizeof(WAVEFORMATEX) + WaveFormat->cbSize;


    //
    //  Then the data header.
    //
    CopyMemory(waveFilePointer, WaveData, sizeof(WaveData));
    waveFilePointer += sizeof(WaveData);
    *(reinterpret_cast<DWORD *>(waveFilePointer)) = static_cast<DWORD>(BufferSize);
    waveFilePointer += sizeof(DWORD);

    //
    //  And finally copy in the audio data.
    //
    CopyMemory(waveFilePointer, Buffer, BufferSize);

    //
    //  Last but not least, write the data to the file.
    //
    DWORD bytesWritten;
    if (!WriteFile(FileHandle, waveFileData, waveFileSize, &bytesWritten, NULL))
    {
        printf("Unable to write wave file: %d\n", GetLastError());
        delete []waveFileData;
        return false;
    }

    if (bytesWritten != waveFileSize)
    {
        printf("Failed to write entire wave file\n");
        delete []waveFileData;
        return false;
    }
    delete []waveFileData;
    return true;
}

//
//  Write the captured wave data to an output file so that it can be examined later.
//
void SaveWaveData(BYTE *CaptureBuffer, size_t BufferSize, const WAVEFORMATEX *WaveFormat)
{
    wchar_t waveFileName[MAX_PATH];
    HRESULT hr = StringCbCopy(waveFileName, sizeof(waveFileName), L"WASAPICaptureEventDriven-");
    if (SUCCEEDED(hr))
    {
        GUID testGuid;
        if (SUCCEEDED(CoCreateGuid(&testGuid)))
        {
            wchar_t *guidString;
            if (SUCCEEDED(StringFromCLSID(testGuid, &guidString)))
            {
                hr = StringCbCat(waveFileName, sizeof(waveFileName), guidString);
                if (SUCCEEDED(hr))
                {
                    hr = StringCbCat(waveFileName, sizeof(waveFileName), L".WAV");
                    if (SUCCEEDED(hr))
                    {
                        HANDLE waveHandle = CreateFile(waveFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 
                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 
                            NULL);
                        if (waveHandle != INVALID_HANDLE_VALUE)
                        {
                            if (WriteWaveFile(waveHandle, CaptureBuffer, BufferSize, WaveFormat))
                            {
                                printf("Successfully wrote WAVE data to %S\n", waveFileName);
                            }
                            else
                            {
                                printf("Unable to write wave file\n");
                            }
                            CloseHandle(waveHandle);
                        }
                        else
                        {
                            printf("Unable to open output WAV file %S: %d\n", waveFileName, GetLastError());
                        }
                    }
                }
                CoTaskMemFree(guidString);
            }
        }
    }
}

我尝试从缓冲区保存音频:

FILE* _file;
int16_t* _data;
_data = (int16_t*)Buffer;
_file = fopen("utterance", "wb +");
fwrite(_data, 1,BufferSize, _file);
fclose(_file);

输出音频是如此糟糕,要查看它,我使用以下代码绘制Raw文件:

import numpy as np
import matplotlib.pyplot as plt
with open ('test.raw', 'rb') as f:
    buf = f.read ()
    data = np.frombuffer (buf, dtype = 'int16')
    L = data [:: 2]
    R = data [1 :: 2]

newdata = np.squeeze(data) # Shape is now: (10, 80)
plt.plot(newdata) # plotting by columns
plt.show()

输出是这个,可以是矩形,声音很害羞:

在此处输入图片说明

我哪里错了?请帮我!

奋斗的太阳-MSFT

检查后,原始音频样本的属性没有问题。请尝试我的代码示例,并添加wav标头以重新编码。

#include <Windows.h>
#include <stdio.h>
#include <MMDeviceAPI.h>
#include <AudioClient.h>
#include <assert.h>
#include <avrt.h>
#include <strsafe.h>
#include <fstream> 

using namespace std;

#pragma warning(disable:4996)

struct WAVEHEADER
{
    DWORD   dwRiff;                     // "RIFF"
    DWORD   dwSize;                     // Size
    DWORD   dwWave;                     // "WAVE"
    DWORD   dwFmt;                      // "fmt "
    DWORD   dwFmtSize;                  // Wave Format Size
};

const BYTE WaveHeader[] =
{
    'R',   'I',   'F',   'F',  0x00,  0x00,  0x00,  0x00, 'W',   'A',   'V',   'E',   'f',   'm',   't',   ' ', 0x00, 0x00, 0x00, 0x00
};

const BYTE WaveData[] = { 'd', 'a', 't', 'a' };

bool WriteWaveFile(HANDLE FileHandle, const BYTE* Buffer, const size_t BufferSize, WAVEFORMATEX* WaveFormat)
{
    DWORD waveFileSize = sizeof(WAVEHEADER) + sizeof(WAVEFORMATEX) + WaveFormat->cbSize + sizeof(WaveData) + sizeof(DWORD) + static_cast<DWORD>(BufferSize);
    BYTE* waveFileData = new (std::nothrow) BYTE[waveFileSize];
    BYTE* waveFilePointer = waveFileData;
    WAVEHEADER* waveHeader = reinterpret_cast<WAVEHEADER*>(waveFileData);

    if (waveFileData == NULL)
    {
        printf("Unable to allocate %d bytes to hold output wave data\n", waveFileSize);
        return false;
    }

    //
    //  Copy in the wave header - we'll fix up the lengths later.
    //
    CopyMemory(waveFilePointer, WaveHeader, sizeof(WaveHeader));
    waveFilePointer += sizeof(WaveHeader);

    //
    //  Update the sizes in the header.
    //
    waveHeader->dwSize = waveFileSize - (2 * sizeof(DWORD));
    waveHeader->dwFmtSize = sizeof(WAVEFORMATEX) + WaveFormat->cbSize;

    //
    //  Next copy in the WaveFormatex structure.
    //
    CopyMemory(waveFilePointer, WaveFormat, sizeof(WAVEFORMATEX) + WaveFormat->cbSize);
    waveFilePointer += sizeof(WAVEFORMATEX) + WaveFormat->cbSize;


    //
    //  Then the data header.
    //
    CopyMemory(waveFilePointer, WaveData, sizeof(WaveData));
    waveFilePointer += sizeof(WaveData);
    *(reinterpret_cast<DWORD*>(waveFilePointer)) = static_cast<DWORD>(BufferSize);
    waveFilePointer += sizeof(DWORD);

    //
    //  And finally copy in the audio data.
    // 

    CopyMemory(waveFilePointer, Buffer, BufferSize);
    //
    //  Last but not least, write the data to the file.
    //
    DWORD bytesWritten;
    if (!WriteFile(FileHandle, waveFileData, waveFileSize, &bytesWritten, NULL))
    {
        printf("Unable to write wave file: %d\n", GetLastError());
        delete[]waveFileData;
        return false;
    }

    if (bytesWritten != waveFileSize)
    {
        printf("Failed to write entire wave file\n");
        delete[]waveFileData;
        return false;
    }
    delete[]waveFileData;
    return true;
}

//
//  Write the captured wave data to an output file so that it can be examined later.
//
void SaveWaveData(BYTE* CaptureBuffer, size_t BufferSize, WAVEFORMATEX* WaveFormat)
{
    wchar_t waveFileName[MAX_PATH];
    HRESULT hr = StringCbCopy(waveFileName, sizeof(waveFileName), L"WASAPICaptureEventDriven-");
    if (SUCCEEDED(hr))
    {
        GUID testGuid;
        if (SUCCEEDED(CoCreateGuid(&testGuid)))
        {
            wchar_t* guidString;
            if (SUCCEEDED(StringFromCLSID(testGuid, &guidString)))
            {
                hr = StringCbCat(waveFileName, sizeof(waveFileName), guidString);
                if (SUCCEEDED(hr))
                {
                    hr = StringCbCat(waveFileName, sizeof(waveFileName), L".WAV");
                    if (SUCCEEDED(hr))
                    {
                        HANDLE waveHandle = CreateFile(waveFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
                            NULL);
                        if (waveHandle != INVALID_HANDLE_VALUE)
                        {
                            if (WriteWaveFile(waveHandle, CaptureBuffer, BufferSize, WaveFormat))
                            {
                                printf("Successfully wrote WAVE data to %S\n", waveFileName);
                            }
                            else
                            {
                                printf("Unable to write wave file\n");
                            }
                            CloseHandle(waveHandle);
                        }
                        else
                        {
                            printf("Unable to open output WAV file %S: %d\n", waveFileName, GetLastError());
                        }
                    }
                }
                CoTaskMemFree(guidString);
            }
        }
    }
}

int main()
{
    long buffersize = 3528000;// For 10s audio sample, we can set the value of buffersize to 3528000
    BYTE* captureBuffer = new (std::nothrow) BYTE[buffersize]; 
    
    FILE* _file;
    _file = fopen("utterance.raw", "rb"); //raw audio path
    fread(captureBuffer, 1, buffersize, _file);
    fclose(_file);

    WAVEFORMATEX wavformat;
    wavformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
    wavformat.nChannels = 2;
    wavformat.nSamplesPerSec = 44100;
    wavformat.nAvgBytesPerSec = 352800;
    wavformat.nBlockAlign = 8;
    wavformat.wBitsPerSample = 32;
    wavformat.cbSize = 22;
    SaveWaveData(captureBuffer, buffersize, &wavformat);

    return 0;
}

您还可以ofstream用来写入原始音频文件。

一些代码:

//  Write the contents of a WAV file.  We take as input the data to write and the format of that data.
//Added in WASAPICaptureSharedEventDriven sample
bool WriteWaveFile(HANDLE FileHandle, const BYTE *Buffer, const size_t BufferSize, const WAVEFORMATEX *WaveFormat)
{
    ofstream binaryFile("file.raw", ios::out | ios::binary);
    binaryFile.write((char*)Buffer, BufferSize);
    binaryFile.close();

    ...

获取原始文件后,使用ifstream来打开文件并添加wav标头。

ifstream infile("utterance.raw", std::ifstream::binary);
 // get size of file
infile.seekg(0, infile.end);
long size = infile.tellg();
infile.seekg(0);

BYTE* captureBuffer = new (std::nothrow) BYTE[size];

infile.read((char*)captureBuffer, size);
infile.close();

WAVEFORMATEX wavformat;
wavformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
wavformat.nChannels = 2;
wavformat.nSamplesPerSec = 44100;
wavformat.nAvgBytesPerSec = 352800;
wavformat.nBlockAlign = 8;
wavformat.wBitsPerSample = 32;
wavformat.cbSize = 22;
SaveWaveData(captureBuffer, size, &wavformat);

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在C ++中通过FFmpeg将原始文件转换为音频文件(.wav)

来自分类Dev

如何在Android NDK中播放音频文件(任何格式)?

来自分类Dev

如何在 Firebase 中保存音频文件

来自分类Dev

如何在原始文件夹android中获取字符串文件名(我的音频文件)

来自分类Dev

如何在Matlab中规范音频文件

来自分类Dev

如何在语音通道中播放特定的音频文件?

来自分类Dev

如何在 ios 中播放 .opus 音频文件

来自分类Dev

如何在javascript中调整音频文件的音量

来自分类Dev

如何在不丢失原始特征的情况下合并视频和音频文件

来自分类Dev

Proguard破坏资产或原始文件中的音频文件

来自分类Dev

如何将原始音频文件设置为铃声

来自分类Dev

在 python 中实时播放原始音频文件

来自分类Dev

如何从IsolatedStorage中读取音频文件?

来自分类Dev

如何从音频文件中识别歌曲?

来自分类Dev

如何在JavaScript或PHP中将WAV音频文件转换为FLAC格式

来自分类Dev

如何在python中将音频文件(wav格式)拼接为1秒的拼接?

来自分类Dev

如何在vba excel中将哔声保存到音频文件

来自分类Dev

如何在客户端保存文本到语音音频文件?

来自分类Dev

目标c中的音频文件格式问题

来自分类Dev

如何查看音频CD中的隐藏音频文件

来自分类Dev

如何编码音频文件并统一保存?

来自分类Dev

如何保存音频文件的位置?目标-C

来自分类Dev

如何保存音频文件并发送它们

来自分类Dev

如何在音频文件中添加图稿以在专辑封面中显示?

来自分类Dev

如何在MATLAB中读取2声道音频文件

来自分类Dev

如何在网页中多次播放同一音频文件?

来自分类Dev

如何在WordPress中显示嵌入式音频文件的标题

来自分类Dev

如何在Python中读取类似于Matlab audioread的音频文件?

来自分类Dev

如何在不使用按钮的情况下在React中播放音频文件?

Related 相关文章

  1. 1

    如何在C ++中通过FFmpeg将原始文件转换为音频文件(.wav)

  2. 2

    如何在Android NDK中播放音频文件(任何格式)?

  3. 3

    如何在 Firebase 中保存音频文件

  4. 4

    如何在原始文件夹android中获取字符串文件名(我的音频文件)

  5. 5

    如何在Matlab中规范音频文件

  6. 6

    如何在语音通道中播放特定的音频文件?

  7. 7

    如何在 ios 中播放 .opus 音频文件

  8. 8

    如何在javascript中调整音频文件的音量

  9. 9

    如何在不丢失原始特征的情况下合并视频和音频文件

  10. 10

    Proguard破坏资产或原始文件中的音频文件

  11. 11

    如何将原始音频文件设置为铃声

  12. 12

    在 python 中实时播放原始音频文件

  13. 13

    如何从IsolatedStorage中读取音频文件?

  14. 14

    如何从音频文件中识别歌曲?

  15. 15

    如何在JavaScript或PHP中将WAV音频文件转换为FLAC格式

  16. 16

    如何在python中将音频文件(wav格式)拼接为1秒的拼接?

  17. 17

    如何在vba excel中将哔声保存到音频文件

  18. 18

    如何在客户端保存文本到语音音频文件?

  19. 19

    目标c中的音频文件格式问题

  20. 20

    如何查看音频CD中的隐藏音频文件

  21. 21

    如何编码音频文件并统一保存?

  22. 22

    如何保存音频文件的位置?目标-C

  23. 23

    如何保存音频文件并发送它们

  24. 24

    如何在音频文件中添加图稿以在专辑封面中显示?

  25. 25

    如何在MATLAB中读取2声道音频文件

  26. 26

    如何在网页中多次播放同一音频文件?

  27. 27

    如何在WordPress中显示嵌入式音频文件的标题

  28. 28

    如何在Python中读取类似于Matlab audioread的音频文件?

  29. 29

    如何在不使用按钮的情况下在React中播放音频文件?

热门标签

归档