2010-11-11 88 views
1

我正在使用音頻單元進行一些自定義音頻後期處理。我有兩個文件合併在一起(下面的鏈接),但是在輸出中會出現一些奇怪的噪音。我究竟做錯了什麼?使用擴展音頻文件服務將兩個文件混合在一起

我已經驗證,在此步驟之前,2個文件(workTrack1workTrack2)處於正確狀態並且聲音良好。在這個過程中也沒有發生錯誤。

緩存處理代碼

- (BOOL)mixBuffersWithBuffer1:(const int16_t *)buffer1 buffer2:(const int16_t *)buffer2 outBuffer:(int16_t *)mixbuffer outBufferNumSamples:(int)mixbufferNumSamples { 
    BOOL clipping = NO; 

    for (int i = 0 ; i < mixbufferNumSamples; i++) { 
     int32_t s1 = buffer1[i]; 
     int32_t s2 = buffer2[i]; 
     int32_t mixed = s1 + s2; 

     if ((mixed < -32768) || (mixed > 32767)) { 
      clipping = YES; // don't break here because we dont want to lose data, only to warn the user 
     } 

     mixbuffer[i] = (int16_t) mixed; 
    } 
    return clipping; 
} 

縮混代碼

//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////  PHASE 4  //////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// In phase 4, open workTrack1 and workTrack2 for reading, 
// mix together, and write out to outfile. 

// open the outfile for writing -- this will erase the infile if they are the same, but its ok cause we are done with it 
err = [self openExtAudioFileForWriting:outPath audioFileRefPtr:&outputAudioFileRef numChannels:numChannels]; 
if (err) { [self cleanupInBuffer1:inBuffer1 inBuffer2:inBuffer2 outBuffer:outBuffer err:err]; return NO; } 

// setup vars 
framesRead = 0; 
totalFrames = [self totalFrames:mixAudioFile1Ref]; // the long one. 
NSLog(@"Mix-down phase, %d frames (%0.2f secs)", totalFrames, totalFrames/RECORD_SAMPLES_PER_SECOND); 

moreToProcess = YES; 
while (moreToProcess) { 

    conversionBuffer1.mBuffers[0].mDataByteSize = LOOPER_BUFFER_SIZE; 
    conversionBuffer2.mBuffers[0].mDataByteSize = LOOPER_BUFFER_SIZE; 

    UInt32 frameCount1 = framesInBuffer; 
    UInt32 frameCount2 = framesInBuffer; 

    // Read a buffer of input samples up to AND INCLUDING totalFrames 
    int numFramesRemaining = totalFrames - framesRead; // Todo see if we are off by 1 here. Might have to add 1 
    if (numFramesRemaining == 0) { 
     moreToProcess = NO; // If no frames are to be read, then this phase is finished 

    } else { 
     if (numFramesRemaining < frameCount1) { // see if we are near the end 
      frameCount1 = numFramesRemaining; 
      frameCount2 = numFramesRemaining; 
      conversionBuffer1.mBuffers[0].mDataByteSize = (frameCount1 * bytesPerFrame); 
      conversionBuffer2.mBuffers[0].mDataByteSize = (frameCount2 * bytesPerFrame); 
     } 

     NSbugLog(@"Attempting to read %d frames from mixAudioFile1Ref", (int)frameCount1); 
     err = ExtAudioFileRead(mixAudioFile1Ref, &frameCount1, &conversionBuffer1); 
     if (err) { [self cleanupInBuffer1:inBuffer1 inBuffer2:inBuffer2 outBuffer:outBuffer err:err]; return NO; } 

     NSLog(@"Attempting to read %d frames from mixAudioFile2Ref", (int)frameCount2); 
     err = ExtAudioFileRead(mixAudioFile2Ref, &frameCount2, &conversionBuffer2); 
     if (err) { [self cleanupInBuffer1:inBuffer1 inBuffer2:inBuffer2 outBuffer:outBuffer err:err]; return NO; } 

     NSLog(@"Read %d frames from mixAudioFile1Ref in mix-down phase", (int)frameCount1); 
     NSLog(@"Read %d frames from mixAudioFile2Ref in mix-down phase", (int)frameCount2); 

     // If no frames were returned, phase is finished 
     if (frameCount1 == 0) { 
      moreToProcess = NO; 

     } else { // Process pcm data 

      // if buffer2 was not filled, fill with zeros 
      if (frameCount2 < frameCount1) { 
       bzero(inBuffer2 + frameCount2, (frameCount1 - frameCount2)); 
       frameCount2 = frameCount1; 
      } 

      const int numSamples = (frameCount1 * bytesPerFrame)/sizeof(int16_t); 

      if ([self mixBuffersWithBuffer1:(const int16_t *)inBuffer1 
            buffer2:(const int16_t *)inBuffer2 
            outBuffer:(int16_t *)outBuffer 
         outBufferNumSamples:numSamples]) { 
       NSLog(@"Clipping"); 
      } 
      // Write pcm data to the main output file 
      conversionOutBuffer.mBuffers[0].mDataByteSize = (frameCount1 * bytesPerFrame); 
      err = ExtAudioFileWrite(outputAudioFileRef, frameCount1, &conversionOutBuffer); 

      framesRead += frameCount1; 
     } // frame count 
    } // else 

    if (err) { 
     moreToProcess = NO; 
    } 
} // while moreToProcess 

// Check for errors 
TTDASSERT(framesRead == totalFrames); 
if (err) { 
    if (error) *error = [NSError errorWithDomain:kUAAudioSelfCrossFaderErrorDomain 
              code:UAAudioSelfCrossFaderErrorTypeMixDown 
             userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:err],@"Underlying Error Code",[self commonExtAudioResultCode:err],@"Underlying Error Name",nil]]; 
    [self cleanupInBuffer1:inBuffer1 inBuffer2:inBuffer2 outBuffer:outBuffer err:err]; 
    return NO; 
} 
NSLog(@"Done with mix-down phase"); 


的假設

  • mixAudioFile1Ref總是長於mixAudioFile2Ref
  • mixAudioFile2Ref用完字節後,outputAudioFileRef應該聽起來完全一樣mixAudioFile2Ref

預期的聲音應該是混合淡入在淡入在軌道環繞時開始產生自交叉淡入淡出。請聽輸出結果,看看代碼,並讓我知道我哪裏錯了。

源音聲http://cl.ly/2g2F2A3k1r3S36210V23
得到的音聲http://cl.ly/3q2w3S3Y0x0M3i2a1W3v

回答

1

原來有在這裏兩個問題。

緩衝處理代碼

int32_t mixed = s1 + s2;是造成剪裁。更好的方法是除以混合的通道數:int32_t mixed = (s1 + s2)/2;然後在另一個通道中稍後進行標準化。

幀!=字節 當歸零第二軌道的緩衝區時,聲音跑了出去,我被錯誤地設定偏移量和持續時間不幀字節。這會在緩衝區中產生垃圾,併產生週期性聽到的噪音。很容易解決:

if (frameCount2 < frameCount1) { 
    bzero(inBuffer2 + (frameCount2 * bytesPerFrame), (frameCount1 - frameCount2) * bytesPerFrame); 
    frameCount2 = frameCount1; 
} 

現在的樣本是偉大的:http://cl.ly/1E2q1L441s2b3e2X2z0J

+0

Iam試圖做同樣的bt不會能夠做到這一點,你可以plz幫助我,, – Aadil 2011-11-21 11:53:33

0

您發佈的答案看起來不錯;我只能看到一個小問題。您的裁剪解決方案,除以兩將有所幫助,但它也相當於應用50%的增益減少。那就是不是正常化一樣; normalization是查看整個音頻文件,查找最高峯值,並應用給定增益降低以使該峯值達到一定水平(通常爲0.0dB)的過程。結果是在正常情況下(即非削波)情況下,輸出信號會非常低,需要再次提升。

在你的混音過程中,你無疑會遇到一個導致失真的溢出,因爲這個值會繞過並導致信號跳躍。你想要做的就是應用一種稱爲「brick-wall limiter」的技術,該技術基本上將硬天花板應用於剪裁的樣本。要做到這一點最簡單的方法是:

int32_t mixed = s1 + s2; 
if(mixed >= 32767) { 
    mixed = 32767; 
} 
else if(mixed <= -32767) { 
    mixed = -32767; 
} 

這種技術的結果是,你會聽到有點失真的周圍被剪裁的樣品,但聲音不會完全錯位的將是整數的情況下,溢出。失真雖然存在,但不會破壞聽覺體驗。

+2

我明白,我在做什麼不是規範化,我在另一個傳遞中應用規範化,通過按比例擴大每個樣本最大峯值達到-0.5db。重讀前面的答案,這是不明確的。編輯。 – coneybeare 2010-11-12 15:15:19

+0

根據實施情況,磚牆限制器與裁剪相同。這取決於如何處理溢出。無論如何,這聽起來很糟糕。在添加樣品之前,我會隨着50%的增益減少,然後正常化。 – lucius 2010-11-22 05:13:48

相關問題