簡體   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