2011-01-07 9 views
7

LPCM生ファイルからチャンネルオーディオを抽出したい、つまりステレオLPCMファイルの左右のチャンネルを抽出します。 LPCMは、16ビット深度、インターリーブド、2チャネル、リトルエンディアンである。私がバイトの順序を収集するものは、{LeftChannel、RightChannel、LeftChannel、RightChannel ...}であり、16ビット深度なので、それぞれのチャネルの右に2バイトのサンプルがありますか?リニアPCMからオーディオチャンネルを抽出する

私は左のチャンネルを抽出したいのですが、私は0,2,4,6 ... n * 2アドレスのバイトを取るでしょうか?右側のチャンネルは1,3,4、...(n * 2 + 1)になります。

また、オーディオチャンネルを抽出した後、抽出したチャンネルのフォーマットを16ビットの深さ、1チャンネルに設定する必要がありますか?

事前

のおかげでこれは私が現在、このコードは非常に抽出され、そのチャネルずに音楽ファイルを書き込んで正常に動作します。.. AssetReaderからのPCMオーディオを抽出するために使用するコードです、それは形式が原因である可能性がありI次のようにまたは何かが...

NSURL *assetURL = [song valueForProperty:MPMediaItemPropertyAssetURL]; 
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil]; 
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
           [NSNumber numberWithFloat:44100.0], AVSampleRateKey, 
           [NSNumber numberWithInt:2], AVNumberOfChannelsKey, 
          // [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey, 
           [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey, 
           [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, 
           [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey, 
           [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, 
           nil]; 
NSError *assetError = nil; 
AVAssetReader *assetReader = [[AVAssetReader assetReaderWithAsset:songAsset 
                  error:&assetError] 
           retain]; 
if (assetError) { 
    NSLog (@"error: %@", assetError); 
    return; 
} 

AVAssetReaderOutput *assetReaderOutput = [[AVAssetReaderAudioMixOutput 
              assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks 
              audioSettings: outputSettings] 
              retain]; 
if (! [assetReader canAddOutput: assetReaderOutput]) { 
    NSLog (@"can't add reader output... die!"); 
    return; 
} 
[assetReader addOutput: assetReaderOutput]; 


NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectoryPath = [dirs objectAtIndex:0]; 

//CODE TO SPLIT STEREO 
[self setupAudioWithFormatMono:kAudioFormatLinearPCM]; 
NSString *splitExportPath = [[documentsDirectoryPath stringByAppendingPathComponent:@"monoleft.caf"] retain]; 
if ([[NSFileManager defaultManager] fileExistsAtPath:splitExportPath]) { 
    [[NSFileManager defaultManager] removeItemAtPath:splitExportPath error:nil]; 
} 

AudioFileID mRecordFile; 
NSURL *splitExportURL = [NSURL fileURLWithPath:splitExportPath]; 


OSStatus status = AudioFileCreateWithURL(splitExportURL, kAudioFileCAFType, &_streamFormat, kAudioFileFlags_EraseFile, 
              &mRecordFile); 

NSLog(@"status os %d",status); 

[assetReader startReading]; 

CMSampleBufferRef sampBuffer = [assetReaderOutput copyNextSampleBuffer]; 
UInt32 countsamp= CMSampleBufferGetNumSamples(sampBuffer); 
NSLog(@"number of samples %d",countsamp); 

SInt64 countByteBuf = 0; 
SInt64 countPacketBuf = 0; 
UInt32 numBytesIO = 0; 
UInt32 numPacketsIO = 0; 
NSMutableData * bufferMono = [NSMutableData new]; 
while (sampBuffer) { 


    AudioBufferList audioBufferList; 
    CMBlockBufferRef blockBuffer; 
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampBuffer, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 
    for (int y=0; y<audioBufferList.mNumberBuffers; y++) { 
     AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
     //frames = audioBuffer.mData; 
     NSLog(@"the number of channel for buffer number %d is %d",y,audioBuffer.mNumberChannels); 
     NSLog(@"The buffer size is %d",audioBuffer.mDataByteSize); 






     //Append mono left to buffer data 
     for (int i=0; i<audioBuffer.mDataByteSize; i= i+4) { 
      [bufferMono appendBytes:(audioBuffer.mData+i) length:2]; 
     } 

     //the number of bytes in the mutable data containing mono audio file 
     numBytesIO = [bufferMono length]; 
     numPacketsIO = numBytesIO/2; 
     NSLog(@"numpacketsIO %d",numPacketsIO); 
     status = AudioFileWritePackets(mRecordFile, NO, numBytesIO, &_packetFormat, countPacketBuf, &numPacketsIO, audioBuffer.mData); 
     NSLog(@"status for writebyte %d, packets written %d",status,numPacketsIO); 
     if(numPacketsIO != (numBytesIO/2)){ 
      NSLog(@"Something wrong"); 
      assert(0); 
     } 


     countPacketBuf = countPacketBuf + numPacketsIO; 
     [bufferMono setLength:0]; 


    } 

    sampBuffer = [assetReaderOutput copyNextSampleBuffer]; 
    countsamp= CMSampleBufferGetNumSamples(sampBuffer); 
    NSLog(@"number of samples %d",countsamp); 
} 
AudioFileClose(mRecordFile); 
[assetReader cancelReading]; 
[self performSelectorOnMainThread:@selector(updateCompletedSizeLabel:) 
         withObject:0 
        waitUntilDone:NO]; 

audiofileservicesと出力フォーマットは以下のとおりです。

 _streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; 
    _streamFormat.mBitsPerChannel = 16; 
    _streamFormat.mChannelsPerFrame = 1; 
    _streamFormat.mBytesPerPacket = 2; 
    _streamFormat.mBytesPerFrame = 2;// (_streamFormat.mBitsPerChannel/8) * _streamFormat.mChannelsPerFrame; 
    _streamFormat.mFramesPerPacket = 1; 
    _streamFormat.mSampleRate = 44100.0; 

    _packetFormat.mStartOffset = 0; 
    _packetFormat.mVariableFramesInPacket = 0; 
    _packetFormat.mDataByteSize = 2; 

答えて

4

はほとんど右サウンド - あなたは16 BIを持っていますこれは、各サンプルが2バイトを取ることを意味します。つまり、左チャンネルのデータはバイト{0,1}、{4,5}、{8,9}などとなります。インターリーブとは、サンプルがインタリーブされ、バイトではないことを意味します。 それ以外は試してみると、コードに問題があるかどうかを確認できます。

またオーディオ チャネルを抽出した後、私は設定する必要があり 16ビット深度 、1つのチャネルとして抽出されたチャネルの形式?

抽出後2つのチャンネルのうち1つだけが残っているので、正しいです。

+0

私は実際にこれを試みましたが、結果は正しくありません...あなたが言ったように抽出アルゴリズムを使用しましたが、出力が歪んで聞こえました...歪んだように、「遅い」と発音します... – Samuel

+0

コード私が上記のアルゴリズムに使用したものは、私のポストに載せられています。入力が間違っていた原因を歓迎します – Samuel

+0

入力サンプルレートは44100ですか?あなたが "遅い"を再生することを説明するその1つ間違っていた場合 – BrokenGlass

1

オーディオが「遅い」と似たエラーが発生しました。この理由は、デュアルチャンネルサウンドを持っているのに対し、mChannelsPerFrameを1に指定したためです。これを2に設定すると、再生が高速化されます。また、これを行った後、正しく出力されているかどうかを教えてください:)

0

ステレオオーディオを2つのモノファイル(split stereo audio to mono streams on iOS)に分割しようとしています。私はあなたのコードを使用していますが、それを動作させるように見えることはできません。あなたのsetupAudioWithFormatMonoメソッドの内容は何ですか?

関連する問題