C 连续录制音频时出现内存问题
在这里,我试图为连续录音的音频系统编写一些代码。然后,当某个振幅阈值被打破时,我尝试在一定时间内录制音频C 连续录制音频时出现内存问题,c,audio,memory-management,deep-copy,portaudio,C,Audio,Memory Management,Deep Copy,Portaudio,在这里,我试图为连续录音的音频系统编写一些代码。然后,当某个振幅阈值被打破时,我尝试在一定时间内录制音频 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <time.h> #include <portaudio.h> #include <sndfile.h> #define FRAMES_
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <portaudio.h>
#include <sndfile.h>
#define FRAMES_PER_BUFFER (1024)
#define SAMPLE_SIZE (4)
typedef struct
{
uint16_t formatType;
uint16_t numberOfChannels;
uint32_t sampleRate;
float* recordedSamples;
} AudioData;
AudioData initAudioData(uint32_t sampleRate, uint16_t channels, int type)
{
AudioData data;
data.formatType = type;
data.numberOfChannels = channels;
data.sampleRate = sampleRate;
return data;
}
float avg(float *data)
{
int elems = sizeof(data) / sizeof(data[0]);
float sum = 0;
for (int i = 0; i < elems; i++)
{
sum += fabs(*(data + i));
}
return (float) sum / elems;
}
int main(void)
{
AudioData data = initAudioData(44100, 2, paFloat32);
PaStream *stream = NULL;
PaError err = paNoError;
int size = FRAMES_PER_BUFFER * data.numberOfChannels * SAMPLE_SIZE;
float *sampleBlock = malloc(size);
float *recordedSamples = NULL;
time_t talking = 0;
time_t silence = 0;
if((err = Pa_Initialize())) goto done;
PaStreamParameters inputParameters =
{
.device = Pa_GetDefaultInputDevice(),
.channelCount = data.numberOfChannels,
.sampleFormat = data.formatType,
.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultHighInputLatency,
.hostApiSpecificStreamInfo = NULL
};
if((err = Pa_OpenStream(&stream, &inputParameters, NULL, data.sampleRate, FRAMES_PER_BUFFER, paClipOff, NULL, NULL))) goto done;
if((err = Pa_StartStream(stream))) goto done;
for(int i = 0;;)
{
err = Pa_ReadStream(stream, sampleBlock, FRAMES_PER_BUFFER);
if(avg(sampleBlock) > 0.000550) // talking
{
printf("You're talking! %d\n", i);
i++;
time(&talking);
recordedSamples = realloc(recordedSamples, size * i);
if (recordedSamples) memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size); // problem here writing to memory at i = 16?
else free(recordedSamples);
}
else //silence
{
double test = difftime(time(&silence), talking);
printf("Time diff: %g\n", test);
if (test >= 1.5)
{
// TODO: finish code processing audio snippet
talking = 0;
free(recordedSamples); // problem freeing memory?
}
}
}
done:
free(sampleBlock);
Pa_Terminate();
return err;
}
Xcode指向这一行是问题所在:
其他时候我运行代码时,会出现以下错误:
这两个错误都让我有些困惑。。。有什么建议吗?//注意:我没有portaudio.h和sndfile.h,因此无法编译/测试
// Note: I do not have the portaudio.h and sndfile.h so could not compile/test
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include "portaudio.h"
#include "sndfile.h"
#define FRAMES_PER_BUFFER (1024)
#define SAMPLE_SIZE (4)
#define NUMBER_OF_CHANNELS (2)
#define SAMPLE_RATE (44100)
#define SIZE (FRAMES_PER_BUFFER * NUMBER_OF_CHANNELS * SAMPLE_SIZE)
static const int size = SIZE;
struct AudioData_t
{
uint16_t formatType;
uint16_t numberOfChannels;
uint32_t sampleRate;
float* recordedSamples;
};
void initAudioData(
struct AudioData_t *pData,
uint32_t sampleRate,
uint16_t channels,
int type)
{
(*pData).formatType = type;
(*pData).numberOfChannels = channels;
(*pData).sampleRate = sampleRate;
} // end function: initAudioData
float averageAudioLevel(float *data)
{
int elems = size / sizeof(float); // <--
float sum = 0;
for (int i = 0; i < elems; i++)
{
sum += fabs(*(data + i));
}
return sum / elems; // sum is float so result is float
} // end function: averageAudioLevel
int main(void)
{
struct AudioData_t data;
initAudioData(&data, SAMPLE_RATE, NUMBER_OF_CHANNELS, paFloat32);
PaStream *stream = NULL;
PaError err = paNoError;
float *sampleBlock = NULL;
if(NULL == (sampleBlock = malloc(size) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
float *recordedSamples = NULL;
time_t talking = 0;
time_t silence = 0;
if( 0 == (err = Pa_Initialize()))
{ // then init successful
PaStreamParameters inputParameters =
{
.device = Pa_GetDefaultInputDevice(),
.channelCount = data.numberOfChannels,
.sampleFormat = data.formatType,
.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultHighInputLatency,
.hostApiSpecificStreamInfo = NULL
};
// if err >0, exit
if( 0 == (err = Pa_OpenStream(&stream, &inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, NULL, NULL)))
{ // then success
if( 0 == (err = Pa_StartStream(stream)) )
{ // then success
int i = 0;
while(1) // this loop never exits
{
talking = 0;
if( 0 == (err = Pa_ReadStream(stream, sampleBlock, FRAMES_PER_BUFFER) ) )
{
if(averageAudioLevel(sampleBlock) > 0.000550) // talking
{
printf("You're talking! %d\n", i);
i++; // counting usable audio samples
if( !talking ) {talking = time(NULL);} // only do once per audio sample
// increase allocation for another audio sample (starts at 0 allocated)
float *temp;
if( NULL == (temp = realloc(recordedSamples, size * i ) )
{ // then realloc failed
perror( ""realloc failed" ");
free( sampleBlock );
free( recordedSamples );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update the actual allocated memory pointer
recordedSamples = temp;
// save the new sample into array of samples
memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size);}
} // end if
}
else //silence
{
if( 0 < i )
{ // then some samples to evaluate
double elapsedTime = difftime(time(NULL), talking);
printf("Time diff: %g\n", elapsedTime);
if (elapsedTime >= 1.5)
{
// TODO: finish code processing audio snippet
// reset time indicators so do not process silence unless proceed by audio sound
talking = 0;
// reset audio sample counter
i = 0;
// dispose of recorded samples
free( recordedSamples );
// prep for next recording
recordedSamples = NULL;
} // end if
} // end if
} // end if
} // end forever loop
} // end if
} // end if
} // end if
free( sampleBlock );
free( recordedSamples );
Pa_Terminate();
return err;
} // end function: main
#包括
#包括
#包括
#包括
#包括
#包括“portaudio.h”
#包括“sndfile.h”
#为每个缓冲区定义帧(1024)
#定义样本大小(4)
#定义\u通道的数量(2)
#定义采样率(44100)
#定义大小(每个缓冲区的帧数*通道数*样本大小)
静态常量int size=大小;
结构音频数据
{
uint16格式类型;
uint16个信道;
uint32_t采样器;
浮动*记录样本;
};
无效音频数据(
结构音频数据,
uint32_t采样器,
uint16_t频道,
int类型)
{
(*pData).formatType=type;
(*pData).numberOfChannels=通道数;
(*pData)。采样器=采样器;
}//结束函数:initAudioData
浮点平均音频电平(浮点*数据)
{
int elems=size/sizeof(float);//defaultHighInputLatency,
.hostApiSpecificStreamInfo=NULL
};
//如果错误>0,则退出
if(0==(err=Pa_OpenStream(&stream,&inputParameters,NULL,采样率,每缓冲区帧数,paClipOff,NULL,NULL)))
{//那就成功了
如果(0==(err=Pa_开始流(stream)))
{//那就成功了
int i=0;
while(1)//此循环从不存在
{
交谈=0;
如果(0==(err=Pa_ReadStream(流、采样块、每缓冲区帧)))
{
if(平均音频电平(采样块)>0.000550)//通话
{
printf(“你在说话!%d\n”,i);
i++;//计算可用音频样本
如果(!talking){talking=time(NULL);}//每个音频样本只执行一次
//增加另一个音频样本的分配(从分配的0开始)
浮动*温度;
if(NULL==(temp=realloc(recordedSamples,size*i))
{//然后realloc失败了
perror(“realloc失败”);
自由(样本块);
免费(记录样品);
退出(退出失败);
}
//否则,realloc将成功
//更新实际分配的内存指针
记录样本=温度;
//将新样本保存到样本数组中
memcpy(recordedSamples+((i-1)*大小),sampleBlock,大小);}
}//如果结束,则结束
}
否则,请保持沉默
{
if(0=1.5)
{
//TODO:完成代码处理音频片段
//重置时间指示器,因此除非通过音频继续,否则不处理静音
交谈=0;
//重置音频采样计数器
i=0;
//处理记录的样品
免费(记录样品);
//准备下一次录音
recordedSamples=NULL;
}//如果结束,则结束
}//如果结束,则结束
}//如果结束,则结束
}//结束永久循环
}//如果结束,则结束
}//如果结束,则结束
}//如果结束,则结束
自由(样本块);
免费(记录样品);
Pa_Terminate();
返回错误;
}//结束函数:main
由于平台的差异,这些类型的错误很难重现,因此我很难准确地知道这里发生了什么,但我将指出您的代码中可能与之相关的一些问题
我注意到您使用free()时出现了一些问题
请注意,free(ptr)不会更改ptr的值,因此后一个错误可能是由以下调用序列引起的:
free(recordSamples);
free(recordSamples);
发生这种情况的原因可能是您可能会两次输入测试>=1.5条件,因此会出现双自由。解决此问题应与添加以下内容一样简单:
recordSamples = NULL;
无论何时调用free。这样,当您第二次调用free时,指针为NULL,您将不会得到错误
这种情况下的另一个潜在问题是,被释放然后传递到realloc的指针将创建未定义的行为。根据实现的不同,它可以愉快地返回无效指针而不抛出任何错误。如果是这种情况,memcpy将失败是有道理的,尽管我不确定e这是否在第一种情况下实际发生。可能在抛出错误之前未刷新某些输出,因此我们可能无法全面了解错误之前调用的内容。调试器对此很有用
我的建议是确保recordSamples在空闲后总是设置为NULL(看起来代码中只有两个),并查看这是否解决了问题。
// Note: I do not have the portaudio.h and sndfile.h so could not compile/test
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include "portaudio.h"
#include "sndfile.h"
#define FRAMES_PER_BUFFER (1024)
#define SAMPLE_SIZE (4)
#define NUMBER_OF_CHANNELS (2)
#define SAMPLE_RATE (44100)
#define SIZE (FRAMES_PER_BUFFER * NUMBER_OF_CHANNELS * SAMPLE_SIZE)
static const int size = SIZE;
struct AudioData_t
{
uint16_t formatType;
uint16_t numberOfChannels;
uint32_t sampleRate;
float* recordedSamples;
};
void initAudioData(
struct AudioData_t *pData,
uint32_t sampleRate,
uint16_t channels,
int type)
{
(*pData).formatType = type;
(*pData).numberOfChannels = channels;
(*pData).sampleRate = sampleRate;
} // end function: initAudioData
float averageAudioLevel(float *data)
{
int elems = size / sizeof(float); // <--
float sum = 0;
for (int i = 0; i < elems; i++)
{
sum += fabs(*(data + i));
}
return sum / elems; // sum is float so result is float
} // end function: averageAudioLevel
int main(void)
{
struct AudioData_t data;
initAudioData(&data, SAMPLE_RATE, NUMBER_OF_CHANNELS, paFloat32);
PaStream *stream = NULL;
PaError err = paNoError;
float *sampleBlock = NULL;
if(NULL == (sampleBlock = malloc(size) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
float *recordedSamples = NULL;
time_t talking = 0;
time_t silence = 0;
if( 0 == (err = Pa_Initialize()))
{ // then init successful
PaStreamParameters inputParameters =
{
.device = Pa_GetDefaultInputDevice(),
.channelCount = data.numberOfChannels,
.sampleFormat = data.formatType,
.suggestedLatency = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice())->defaultHighInputLatency,
.hostApiSpecificStreamInfo = NULL
};
// if err >0, exit
if( 0 == (err = Pa_OpenStream(&stream, &inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, NULL, NULL)))
{ // then success
if( 0 == (err = Pa_StartStream(stream)) )
{ // then success
int i = 0;
while(1) // this loop never exits
{
talking = 0;
if( 0 == (err = Pa_ReadStream(stream, sampleBlock, FRAMES_PER_BUFFER) ) )
{
if(averageAudioLevel(sampleBlock) > 0.000550) // talking
{
printf("You're talking! %d\n", i);
i++; // counting usable audio samples
if( !talking ) {talking = time(NULL);} // only do once per audio sample
// increase allocation for another audio sample (starts at 0 allocated)
float *temp;
if( NULL == (temp = realloc(recordedSamples, size * i ) )
{ // then realloc failed
perror( ""realloc failed" ");
free( sampleBlock );
free( recordedSamples );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
// update the actual allocated memory pointer
recordedSamples = temp;
// save the new sample into array of samples
memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size);}
} // end if
}
else //silence
{
if( 0 < i )
{ // then some samples to evaluate
double elapsedTime = difftime(time(NULL), talking);
printf("Time diff: %g\n", elapsedTime);
if (elapsedTime >= 1.5)
{
// TODO: finish code processing audio snippet
// reset time indicators so do not process silence unless proceed by audio sound
talking = 0;
// reset audio sample counter
i = 0;
// dispose of recorded samples
free( recordedSamples );
// prep for next recording
recordedSamples = NULL;
} // end if
} // end if
} // end if
} // end forever loop
} // end if
} // end if
} // end if
free( sampleBlock );
free( recordedSamples );
Pa_Terminate();
return err;
} // end function: main
free(recordSamples);
free(recordSamples);
recordSamples = NULL;
recordedSamples = realloc(recordedSamples, size * i);
memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size);