2011-01-07 34 views
7

Tôi muốn trích xuất âm thanh kênh từ tệp thô LPCM, tức là trích xuất kênh trái và phải của tệp LPCM âm thanh nổi. LPCM có độ sâu 16 bit, xen kẽ, 2 kênh, kết thúc bằng litle. Từ những gì tôi thu thập thứ tự của byte là {LeftChannel, RightChannel, LeftChannel, RightChannel ...} và vì nó là độ sâu 16 bit sẽ có 2 byte mẫu cho mỗi kênh phải không?Trích xuất kênh âm thanh từ Linear PCM

Vì vậy, câu hỏi của tôi là nếu tôi muốn trích xuất kênh bên trái thì tôi sẽ lấy các byte trong 0,2,4,6 ... n * 2 địa chỉ? trong khi kênh phải là 1,3,4, ... (n * 2 + 1).

Ngoài ra sau khi trích xuất kênh âm thanh, tôi có nên đặt định dạng của kênh được trích xuất ở độ sâu 16 bit, 1 kênh không?

Cảm ơn trước

Đây là mã mà tôi hiện đang sử dụng để trích xuất âm thanh PCM từ AssetReader .. Mã này hoạt động tốt với viết một tập tin âm nhạc mà không cần kênh của nó được chiết xuất vì vậy tôi nó có thể được gây ra bởi các định dạng hoặc một cái gì đó ...

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]; 

Các định dạng đầu ra với audiofileservices được như sau:

 _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; 

Trả lời

4

Âm thanh gần như ngay - bạn có một bi 16 t chiều sâu, do đó có nghĩa là mỗi mẫu sẽ mất 2 byte. Điều đó có nghĩa là dữ liệu kênh bên trái sẽ bằng byte {0,1}, {4,5}, {8,9}, v.v. Interleaved có nghĩa là các mẫu được xen kẽ, không phải các byte. Khác hơn là tôi sẽ thử nó ra và xem nếu bạn có bất kỳ vấn đề với mã của bạn.

Ngoài ra sau khi giải nén các kênh âm thanh , tôi nên thiết lập các định dạng của kênh chiết xuất như 16 bit độ sâu , 1 kênh?

Chỉ một trong hai kênh còn lại sau khi trích xuất của bạn, vì vậy có, điều này là chính xác.

+0

Được rồi tôi thực sự đã thử điều này và kết quả là không đúng ... Tôi đã sử dụng thuật toán trích xuất như bạn đã nói nhưng âm thanh đầu ra bị méo ... bị méo như trong, âm thanh "chậm" ... – Samuel

+0

Mã mà tôi đã sử dụng cho thuật toán đã nói đã được đưa lên trong bài viết của tôi. Tôi sẽ hoan nghênh bất kỳ đầu vào nào gây ra lỗi sai – Samuel

+0

Bạn có chắc chắn rằng tỷ lệ mẫu đầu vào là 44100? Nếu bạn đã có một sai lầm đó sẽ giải thích nó chơi lại "chậm" – BrokenGlass

1

Tôi đã gặp lỗi tương tự như âm thanh có vẻ 'chậm', lý do cho điều này là bạn đã chỉ định mChannelsPerFrame là 1, trong khi bạn có âm thanh kênh kép. Đặt nó thành 2 và nó sẽ tăng tốc độ phát lại. Ngoài ra hãy nói nếu sau khi bạn thực hiện điều này, đầu ra 'âm thanh' chính xác ... :)

0

Tôi đang cố gắng chia âm thanh nổi thành hai tệp đơn (split stereo audio to mono streams on iOS). Tôi đã sử dụng mã của bạn nhưng dường như không thể làm cho nó hoạt động. Nội dung của phương thức setupAudioWithFormatMono của bạn là gì?

Các vấn đề liên quan