RT如图所示代码中frames打印出结果为100,但是代码却不执行循环体,仔细检查过循环体里面没有break。return等语句,请问一下问题出在哪啊?(取消142行注释能够正打印出0到99)
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
struct WAV_Format {
uint32_t ChunkID; /* "RIFF" */
uint32_t ChunkSize; /* 36 + Subchunk2Size */
uint32_t Format; /* "WAVE" */
/* sub-chunk "fmt" */
uint32_t Subchunk1ID; /* "fmt " */
uint32_t Subchunk1Size; /* 16 for PCM */
uint16_t AudioFormat; /* PCM = 1*/
uint16_t NumChannels; /* Mono = 1, Stereo = 2, etc. */
uint32_t SampleRate; /* 8000, 44100, etc. */
uint32_t ByteRate; /* = SampleRate * NumChannels * BitsPerSample/8 */
uint16_t BlockAlign; /* = NumChannels * BitsPerSample/8 */
uint16_t BitsPerSample; /* 8bits, 16bits, etc. */
/* sub-chunk "data" */
uint32_t Subchunk2ID; /* "data" */
uint32_t Subchunk2Size; /* data size */
};
//Data Chunk
// ==================================
// | |所占字节数| 具体内容 |
// ==================================
// | ID | 4 Bytes | 'data' |
// ----------------------------------
// | Size | 4 Bytes | |
// ----------------------------------
// | data | | |
// ----------------------------------
// 图5 Data Chunk
//
// Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是
//数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,
//wav数据的bit位置可以分成以下几种形式:
// ---------------------------------------------------------------------
// | 单声道 | 取样1 | 取样2 | 取样3 | 取样4 |
// |--------------------------------------------------------------------
// | 8bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |
// ---------------------------------------------------------------------
// | 双声道 | 取样1 | 取样2 |
// |--------------------------------------------------------------------
// | 8bit量化 | 声道0(左) | 声道1(右) | 声道0(左) | 声道1(右) |
//
//
// ----------------------------------------------------------------------
//
// | 单声道 | 取样1 | 取样2 |
// |---------------------------------------------------------------------
// | 16bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |
// | | (低位字节) | (高位字节) | (低位字节) | (高位字节)|
// -----------------------------------------------------------------------
//
// | 双声道 | 取样1 | 取样2 |
// |-------------------------------------------------------------------------------
// | 16bit量化 | 声道0(左) | 声道0(左) | 声道1(左) | 声道1(右)|
// | | (低位字节) | (高位字节) | (低位字节) | (高位字节) |
// ---------------------------------------------------------------------------------
struct BLOCK_16bit_2channel {
uint8_t channel_left_low;
uint8_t channel_left_high;
uint8_t channel_right_low;
uint8_t channel_right_high;
};
struct DATA_BLOCK {
char strData[4]; // 'd' 'a' 't' 'a'
uint32_t dwDataSize;
// BLOCK_16bit_2channel block
};
int main(void)
{
FILE *fp = NULL;
struct WAV_Format wav;
struct DATA_BLOCK data;
struct BLOCK_16bit_2channel block;
fp = fopen("test.wav", "rb");
if (!fp) {
printf("can't open audio file\n");
exit(1);
}
fread(&wav, 1, sizeof(struct WAV_Format), fp);
printf("length:%d(10),0x%x, \n\n", sizeof(struct WAV_Format), sizeof(struct WAV_Format)); // 44
printf("ChunkID \t%x\n", wav.ChunkID);
printf("ChunkSize \t%d\n", wav.ChunkSize);
printf("Format \t\t%x\n", wav.Format);
printf("Subchunk1ID \t%x\n", wav.Subchunk1ID);
printf("Subchunk1Size \t%d\n", wav.Subchunk1Size);
printf("AudioFormat \t%d\n", wav.AudioFormat);
printf("NumChannels \t%d\n", wav.NumChannels);
printf("SampleRate \t%d\n", wav.SampleRate);
printf("ByteRate \t%d\n", wav.ByteRate);
printf("BlockAlign \t%d\n", wav.BlockAlign);
printf("BitsPerSample \t%d\n", wav.BitsPerSample);
printf("Subchunk2ID \t%x\n", wav.Subchunk2ID);
printf("Subchunk2Size \t%d\n", wav.Subchunk2Size);
// fread(&data, 1, sizeof(struct DATA_BLOCK), fp);
// printf("dwDataSize \t%x\n", data.dwDataSize);
char data_block;
uint16_t lh;
uint16_t ll;
uint16_t rh;
uint16_t rl;
struct Spectrum {
unsigned int s1;
unsigned int s2;
unsigned int s3;
unsigned int s4;
unsigned int s5;
unsigned int s6;
unsigned int s7;
unsigned int s8;
};
// unsigned short sample;
if (wav.BitsPerSample == 16) {
if (wav.NumChannels == 2) {
int i;
long count = wav.Subchunk2Size / sizeof(struct BLOCK_16bit_2channel);
int duration = count / wav.SampleRate; // 采样数量除以每秒采样率等于持续秒数
short fps = 10; // frequency
int frames = duration * fps;
int readSamplePer = wav.SampleRate / fps; // 每秒读取采样数量
int readBytesPer = sizeof(struct BLOCK_16bit_2channel) * readSamplePer; // 每秒读取字节数
short width = 80;
int total = fps * wav.SampleRate / width;
int left, right;
// for (int s=0; s<frames; ++s)printf("\n%d\n", s);
printf("\nframe:%d\n", frames);
for (int s=0; s<frames; ++s) {
printf("\n%d\n", s);
struct Spectrum spectrum;
// fread(&sample, 1, readSamplePer, fp);
for (int r=0; r<readBytesPer; ++r) {
fread(&block, 1, readBytesPer, fp);
lh = block.channel_left_high;
ll = block.channel_left_low;
rh = block.channel_right_high;
rl = block.channel_right_low;
left = (lh << 4) | ll;
right = (rh << 4) | rl;
uint32_t sample = (left + right) / 2;
printf("\n%d\n", sample);
if (sample < 4096 * 1) {
++spectrum.s1;
}
if (sample < 4096 * 2) {
++spectrum.s2;
}
if (sample < 4096 * 3) {
++spectrum.s3;
}
if (sample < 4096 * 4) {
++spectrum.s4;
}
if (sample < 4096 * 5) {
++spectrum.s5;
}
if (sample < 4096 * 6) {
++spectrum.s6;
}
if (sample < 4096 * 7) {
++spectrum.s7;
}
if (sample < 4096 * 8) {
++spectrum.s8;
}
}
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", spectrum.s1, spectrum.s2, spectrum.s3, spectrum.s4, spectrum.s5, spectrum.s6, spectrum.s7, spectrum.s8);
}
// for (i=0; i<count; i+=frequency) {
// fread(&block, 1, sizeof(struct BLOCK_16bit_2channel), fp);
// lh = block.channel_left_high;
// ll = block.channel_left_low;
// rh = block.channel_right_high;
// rl = block.channel_right_low;
// left = (lh << 4) | ll;
// right = (rh << 4) | rl;
//// printf("%d:\t%d\t%d\n", i, left, right);
// }
// printf("\ni:%d,count:%d\n", i, count);
// system("cls");
}
}
fclose(fp);
return 0;
}
首先
循环体执行了。
log上有个
0
,说明第一次s=0的时候进入循环了。然后
看起来像是没有执行,是因为程序崩溃了。
最后的报错信息
process excited after ... with return value 3221225477
崩溃的原因
出问题的应该是第149行的
读取长度远远超出buff,内存读写越界了,导致最后程序崩溃。🎜fread(&block, 1, readBytesPer, fp);
fread(&block, 1, readBytesPer, fp);
作为buff的
block
,其长度只有一个struct BLOCK_16bit_2channel
但是读取的长度readBytesPer
= sizeof(struct BLOCK_16bit_2channel) * readSamplePer
作为buff的block
,其长度只有一个struct BLOCK_16bit_2channel
但是读取的长度readBytesPer
= sizeof(struct BLOCK_16bit_2channel) * readSamplePer
,其中readSamplePer的值为22050*10