录制的声音比原始声音慢

Posted

技术标签:

【中文标题】录制的声音比原始声音慢【英文标题】:Sound recorded is slower that the original one 【发布时间】:2015-08-13 11:54:10 【问题描述】:

我正在尝试实现循环功能。基本上我将音乐样本保存在缓冲区中。 然后,当我按下循环输入按钮时,我会及时设置初始循环,按下循环输出时会设置循环结束时间。 为了获得循环部分,我制作了循环时间 - 及时循环,这给了我循环的秒数。然后我乘以秒 * 采样率 (44100),分配一个具有该大小的新缓冲区并用声音数据填充它。 一切正常,但是当我通过 Open SL ES 收听循环缓冲区时,声音比原来的慢。 我真的不知道为什么......

SLmillisecond loopInPosition, loopOutPosition;
float loopDuration;
const char *lastPath;
short *sampleBuffer, *loopBuffer;
int xSampleBufferSize, xLoopBuffersize;

void playBuffer();

// get the position in the music sample when loop in or out button is pressed
SLmillisecond getCurrentPosition(jint playerIndex, SLmillisecond* whereToSave) 

    Player player = players[playerIndex];
    if (player.isReady == 1) 
        (*(player.playerPlayItf))->GetPosition(player.playerPlayItf,
                whereToSave);

        __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
                ">>NATIVE position is: %d", *whereToSave);
    


void loopIn(JNIEnv* env,
        jclass clazz, jint selectedSlot, jstring filename) 

    lastPath = (*env)->GetStringUTFChars(env, filename, NULL);
    assert(NULL != path);

    getCurrentPosition(selectedSlot, &loopInPosition);


void loopOut(JNIEnv* env,
        jclass clazz, jint selectedSlot) 

    getCurrentPosition(selectedSlot, &loopOutPosition);

    loopDuration = (float) ((float) (loopOutPosition - loopInPosition) / 1000);

    __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
            ">>NATIVE loop duration is: %f", loopDuration);

    SF_INFO sndInfo;
    SNDFILE *sndFile = sf_open(lastPath, SFM_READ, &sndInfo);

    if (sndInfo.format != (SF_FORMAT_WAV | SF_FORMAT_PCM_16)) 
        fprintf(stderr, "Input should be 16bit Wav\n");
        sf_close(sndFile);
     else 

        __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
                ">>NATIVE File info samplerate %d, channels %d, format %d, sections %d, seekable %d",
                sndInfo.samplerate, sndInfo.channels, sndInfo.format,
                sndInfo.sections, sndInfo.seekable);
    

    // Sample Buffer
    int sampleBufferSize = sndInfo.frames * sizeof(short);
    xSampleBufferSize = sampleBufferSize;
    sampleBuffer = malloc(sampleBufferSize);


    __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
            ">>NATIVE allocated sample buffer: size %d, frames %d",
            sampleBufferSize, sndInfo.frames);

    sf_readf_short(sndFile, sampleBuffer, sndInfo.frames);

    // Loop Buffer
    int loopBufferSize = loopDuration * 44100 * sizeof(short);
    int loopBufferFrames = loopDuration * 44100;
    xLoopBuffersize = loopBufferSize;
    loopBuffer = malloc(loopBufferSize);

    __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
            ">>NATIVE allocated loop buffer: size %d, frames %d",
            loopBufferSize, loopBufferFrames);

    int index, i = 0;
    int startIndex = (int) ((float) (loopInPosition / 1000) * 44100);

    __android_log_print(ANDROID_LOG_DEBUG, "jajaja",
            ">>NATIVE start index is %d", startIndex);

    for (index = startIndex, i = 0; index < startIndex + loopBufferFrames;
            ++index, ++i) 

        loopBuffer[i] = sampleBuffer[index];
    

感谢您的宝贵时间

【问题讨论】:

听起来像采样率不匹配。慢了多少? 是立体声音频吗?另外,你听到的是整个循环还是只是其中的一部分(比如一半)? 频率也低吗? 我听到所有的循环和频率似乎是一样的,但我真的没有检查它。我现在正准备着手处理它,我不知道为什么如果我将最后几行更改为 loopBuffer[i] = sampleBuffer[index * 2]...效果很好...你能解释一下吗? 如果你知道要改变什么才能让它听起来正确,你为什么要在这个论坛上提问? 【参考方案1】:

似乎正在发生的事情是您正在处理交错的立体声数据。这意味着两个通道都存储为一个连续的块:第一个通道的样本,第二个通道的样本,第一个通道的样本再次等等。

但是,您的缓冲区是作为单声道播放的,因此在播放时,它认为用于第二个通道的每个样本都用于第一个(也是唯一的)通道。这会创建重复的样本,使其听起来更慢。

当您执行loopBuffer[i] = sampleBuffer[index * 2] 时,实际上您跳过了用于第一个通道的每个样本,只复制了用于第二个通道的样本。

您可能希望将音频播放器配置为将缓冲区解释为交错立体声数据。

【讨论】:

以上是关于录制的声音比原始声音慢的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 在录制视频时播放音频/声音

macos系统实现用ffmpeg录制屏幕和录制声音命令

使用 NAudio 使用 asioout 录制时如何使声音更大?

如何使用 Windows API 从麦克风录制 wav 声音?

屏幕录制时没有声音是怎么回事

以编程方式录制声音发送到内置输出,Mac OS X