将读取的字节数转换为读取的秒数
Converting Bytes read to seconds read
我正在从 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);
我觉得你有点搞混了。假设 WAV header 中的字段名称如 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
作为大小即可。
如果您想为 样本 分配内存,那么它会根据音频是 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;
我正在从 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);
我觉得你有点搞混了。假设 WAV header 中的字段名称如 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
作为大小即可。
如果您想为 样本 分配内存,那么它会根据音频是 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;