2

我正在从 Riff wav fmt 文件中读取数据,我有一个DataBufferwav 文件的数据块数组,如何将读取的数据字节数转换为从 wav 文件中读取的秒数。

int size_buffer = (Subchunk2Size / (NumOfChan * bitsPerSample / 8));
FILE* WavResult = fopen(FileNom, "rb");
u8* DataBuffer = new u8[size_buffer];
size_t nRead = fread(DataBuffer, sizeof DataBuffer[0], size_buffer, WavResult);
4

1 回答 1

1

我觉得你把事情搞混了。假设 WAV 标头中的字段名称如http://soundfile.sapp.org/doc/WaveFormat中所述:

ChunkID - "RIFF"
ChunkSize
    Format - "WAVE"
    Subchunk1ID - "fmt "
    Subchunk1Size
        AudioFormat
        NumChannels
        SampleRate
        ByteRate
        BlockAlign
        BitsPerSample
    Subchunk2ID - "data"
    Subchunk2Size
        data

你的这一行:

int size_buffer = (Subchunk2Size / (NumOfChan * bitsPerSample / 8));

计算单个通道中的多个样本。或多个块,其中块是每个通道包含一个样本的结构。如果您使用它为块中的字节分配内存,那么data仅在 8 位单声道音频的情况下就足够了。

如果为字节分配内存确实是您想要的,那么只需将Subchunk2Size其用作大小。

如果您想为samples分配内存,那么它会根据音频是 8 位还是 16 位而有所不同(我忽略了其他可能性)。对于 8 位:

const uint32_t num_of_samples = Subchunk2Size / (BitsPerSample / 8);
uint8_t *samples = new uint8_t[num_of_samples];

对于 16 位:

const uint32_t num_of_samples = Subchunk2Size / (BitsPerSample / 8);
int16_t *samples = new int16_t[num_of_samples];

就个人而言,我宁愿使用std::vector而不是 c-arrays:

const uint32_t num_of_samples = Subchunk2Size / (BitsPerSample / 8);
std::vector<int16_t> samples;
samples.resize(num_of_samples);    // could be done in the constructor, but I am afraid of vector constructors ;-)

我还假设音频采用最流行的编码(我认为),即 8 位无符号和 16 位有符号。我也忽略了字节顺序的问题。


但回到秒数。我们可以使用块的总数和 来计算SampleRateSampleRate告诉我们每秒有多少样本(在单个通道中)。或者换句话说,每秒有多少块。所以秒数是:

const double num_of_seconds = 1.0 * num_of_blocks / SampleRate;

您可以使用第一行中的公式计算块数:

const uint32_t num_of_blocks = Subchunk2Size / (NumChannels * BitsPerSample / 8);

或者,正如我们已经拥有的num_of_samples,这是来自所有通道的样本总数,我们可以将其除以NumChannels

const uint32_t num_of_blocks = num_of_samples / NumChannels;

最后,如果您真正想要的只是从字节数中获取秒数,那么有 2 个选项。您可以计算块大小:

const int block_size = NumChannels * BitsPerSample / 8;

这应该与 基本相同BlockAlign,然后除以Subchunk2Size它,得到块数,再除以SampleRate得到秒数:

const double num_of_seconds = 1.0 * Subchunk2Size / block_size / SampleRate;
// or
const double num_of_seconds = 1.0 * Subchunk2Size / BlockAlign / SampleRate;

或者您可以使用ByteRate,这是每秒的字节数:

const double num_of_seconds = 1.0 * Subchunk2Size / ByteRate;
于 2021-12-03T01:58:04.693 回答