连续录制音频时出现内存问题

syb*_*0rg 10 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_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;
}
Run Code Online (Sandbox Code Playgroud)

但是,代码有点挑剔.有时当我在Xcode中运行我的程序时,我得到以下输出:

Time diff: 1.4218e+09
You're talking! 0
You're talking! 1
You're talking! 2
You're talking! 3
You're talking! 4
You're talking! 5
You're talking! 6
You're talking! 7
You're talking! 8
You're talking! 9
You're talking! 10
You're talking! 11
You're talking! 12
You're talking! 13
You're talking! 14
You're talking! 15
(lldb)
Run Code Online (Sandbox Code Playgroud)

Xcode指向这一行是问题所在:

if (recordedSamples) memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size); // problem here writing to memory at i = 16?
Run Code Online (Sandbox Code Playgroud)

其他时候我运行代码,我收到此错误:

Time diff: 1.4218e+09
You're talking! 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 0
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 1
Time diff: 2
Time diff: 1.4218e+09
CTestEnvironment(55085,0x7fff7938e300) malloc: *** error for object 0x10081ea00: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Run Code Online (Sandbox Code Playgroud)

这两个错误都让我感到困惑......有什么建议吗?

sth*_*sth 6

您正在写出已分配缓冲区的范围:

recordedSamples = realloc(recordedSamples, size * i);
memcpy(recordedSamples + ((i - 1) * size), sampleBlock, size);
Run Code Online (Sandbox Code Playgroud)

realloc()这里分配一定数量的字节size * i.生成的指针存储在recordedSamples其中,具有类型float*.

memcpy()随后试图将数据写入recordedSamples + ((i - 1) * size.指针算术用于确定应写入的位置.由于recordedSamples是类型float*,recordedSample + X指向X浮点值(不是X字节)的偏移量.

换句话说,recordedSamples + ((i - 1) * size指向((i - 1) * size * sizeof(float)后面的内存位置字节recordedSamples.这通常不在分配的缓冲区内,因为浮点数大于单个字节.

要解决这个问题,最大的问题是if size是多少字节还是多个浮点数.这取决于您正在使用的API函数,我没有详细研究过它.

如果它是一个floats,那么你必须调整对基本内存管理函数的调用malloc,realloc并且memcpy,因为全部操作字节.而不是malloc(size)你会打电话malloc(size * sizeof(float)).

如果size确实是一些字节,那么在进行带字节偏移的指针算法之前制作recordedSamplesa char*或者至少强制转换它会更合乎逻辑memcpy((char*)recordedSamples + ...).