繁体   English   中英

如何在iOS上的音频缓冲区中跳过样本

[英]How to skip samples in an audio buffer on iOS

我正在尝试跳过或缩短iOS上音频播放的静音。 使用RemoteIO,我将以下代码段用于消除静音的逻辑。 但是,它不能正常工作。 根据代码,我希望可以从samples消除静音,并使音频以最小的速度播放(因为样本会被删除)。 但是,相反,我有时会听到奇怪的弹出声/咔嗒声,并且音频定时是相同的(什么都不会跳过,就像消除了静音一样)。

有什么想法我做错了吗? 这是错误的做法吗?

// original samples are stored in renderBufferList
// loop through the samples and replace anything less than amplitudeThreshold 
// with the next "non-silent" sample

SInt16 *samples = renderBufferList->mBuffers[0].mData;
int sampleCount = renderBufferList->mBuffers[0].mDataByteSize / sizeof(SInt16);
int currentSampleIndex = 0;
int amplitudeThreshold = 15;
int channels = 2;
for (int i = 0; i < sampleCount; i+=channels) {
    SInt16 sampleL = samples[i];
    SInt16 sampleR = samples[i+1];
    // check if amplitude of sample is > amplitudeThreshold
    if (abs(sampleL) > amplitudeThreshold || abs(sampleR) > amplitudeThreshold) {
        // set samples and increase to next sample set
        samples[currentSampleIndex] = sampleL;
        samples[currentSampleIndex+1] = sampleR;
        currentSampleIndex+=channels;
    }
}

// how many bytes should be in non-amplitudeThreshold samples
int bytesToCopy = currentSampleIndex * sizeof(SInt16);

if (bytesToCopy > 0) {
    // store samples in circular buffer
    TPCircularBufferProduceBytes(&circularBuffer, samples, bytesToCopy);
} else {
    // set buffer to silence
    memset((SInt16*)inIoData->mBuffers[0].mData, 0, bytesToCopy);
    return noErr;
}

int outputDataByteSize = inIoData->mBuffers[0].mDataByteSize;
SInt16 *outputBuffer = (SInt16*)inIoData->mBuffers[0].mData;

// if circularBuffer is filled more than outputDataByteSize * 10 (large buffer)
if (circularBuffer.fillCount > outputDataByteSize * 10) {

    int32_t availableBytes;
    SInt16 *buffer = TPCircularBufferTail(&circularBuffer, &availableBytes);
    if(buffer == NULL) {
        NSLog(@"circular buffer is empty. end of track.");
        return noErr;
    }

    int numBytes = MIN(bytesToCopy, availableBytes);
    memcpy(outputBuffer, buffer, numBytes);

    // consume (remove) bytes from circular buffer that are being copied to output buffer
    TPCircularBufferConsume(&circularBuffer, numBytes);
}
else {
    NSLog(@"buffering");
    memset(targetBuffer, 0, outputDataByteSize);
    return noErr;
}

查看静默检测逻辑(我不是IOS / swift程序员),似乎您正在逐个样本地定义静默。 这不是音频的工作方式,基本上您要做的就是剪切波形中低于振幅阈值的部分-导致咔嗒声,因为波形的上部仍然存在,所以静音/低振幅数据仍然有些在那里(尽管已损坏)。

我建议计算音频的振幅,即样本的一些子集,而不是硬切成0,而是线性上/下移动以消除咔嗒声。

还有一点,您的样本采用什么格式? -1:1个PCM? 如果您还没有这样做,那么基于分贝而不是原始数据来检测沉默也是值得的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM