【问题标题】:Converting Bytes read to seconds read将读取的字节转换为读取的秒数
【发布时间】:2022-01-09 06:18:07
【问题描述】:

我正在从 Riff wav fmt 文件中读取数据,我有一个 wav 文件的数据块 DataBuffer 的数组,如何将读取的数据字节数转换为从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);

【问题讨论】:

    标签: c++11 wav riff


    【解决方案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块中的bytes分配内存,那么只有在8位单声道音频的情况下就足够了。

    如果为 bytes 分配内存确实是您想要的,那么只需使用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 位有符号。我也忽略了字节序的问题。


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

    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;
    

    【讨论】:

      猜你喜欢
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-20
      • 2018-01-29
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      相关资源
      最近更新 更多