2011-01-07 22 views
7

से ऑडियो चैनल निकालने के लिए मैं एक एलपीसीएम कच्ची फ़ाइल से एक चैनल ऑडियो निकालना चाहता हूं यानी एक स्टीरियो एलपीसीएम फ़ाइल के बाएं और दाएं चैनल निकालें। एलपीसीएम 16 बिट गहराई, इंटरलीव किया गया, 2 चैनल, लिटल एंडियन है। बाइट के आदेश को इकट्ठा करने से मैं {LeftChannel, RightChannel, LeftChannel, RightChannel ...} और चूंकि यह 16 बिट गहराई है, प्रत्येक चैनल के लिए नमूना के 2 बाइट सही होंगे?रैखिक पीसीएम

तो मेरा सवाल यह है कि अगर मैं बाएं चैनल निकालना चाहता हूं तो मैं बाइट्स को 0,2,4,6 ... एन * 2 पता में ले जाऊंगा? जबकि सही चैनल 1,3,4 होगा, ... (एन * 2 + 1)।

ऑडियो चैनल निकालने के बाद, क्या मुझे निकाले गए चैनल का प्रारूप 16 बिट गहराई, 1 चैनल के रूप में सेट करना चाहिए?

अग्रिम

यह धन्यवाद कोड है कि मैं वर्तमान में .. इस कोड को अपने चैनल के बिना एक संगीत फ़ाइल को लिखने के लिए ठीक काम करता है AssetReader से PCM ऑडियो को निकालने के लिए उपयोग करती हैं इसलिए मैं इसे प्रारूप के कारण हो सकती निकाला जा रहा है या कुछ और ...

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 द्वि है टी गहराई, तो इसका मतलब है कि प्रत्येक नमूना 2 बाइट लेगा। इसका मतलब है कि बाएं चैनल डेटा बाइट्स {0,1}, {4,5}, {8,9} और इसी तरह होगा। इंटरलीव का मतलब है कि नमूनों को बाइट नहीं किया जाता है। इसके अलावा मैं इसे आज़माउंगा और देख सकता हूं कि आपको अपने कोड के साथ कोई समस्या है या नहीं।

इसके अलावा ऑडियो चैनल निकालने के बाद, मैं स्थापित करना चाहिए के रूप में 16 बिट गहराई , 1 चैनल निकाले चैनल के प्रारूप?

आपके निष्कर्षण के बाद केवल दो चैनलों में से एक शेष है, इसलिए हाँ, यह सही है।

+0

ठीक है, मैंने वास्तव में इसका प्रयास किया है और नतीजा सही नहीं है ... मैंने निकाले गए एल्गोरिदम का उपयोग किया जैसा आपने कहा है लेकिन आउटपुट विकृत लगता है ... जैसा विकृत होता है, यह "धीमा" लगता है ... – Samuel

+0

कोड कि मैंने कहा है कि मेरे पोस्ट में कहा गया एल्गोरिदम रखा गया है। मैं किसी भी इनपुट का स्वागत करता हूं जिसके कारण यह गलत हो जाता है – Samuel

+0

क्या आप सुनिश्चित हैं कि इनपुट नमूना दर 44100 है? यदि आपके पास वह गलत था जो इसे "धीमा" – BrokenGlass

1

मुझे एक समान त्रुटि थी कि ऑडियो 'धीमा' लग रहा था, इसका कारण यह है कि आपने 1 के mChannelsPerFrame निर्दिष्ट किया है, जबकि आपके पास दोहरी चैनल ध्वनि है। इसे 2 पर सेट करें और इसे प्लेबैक को तेज करना चाहिए। यह भी बताएं कि क्या आप इसे आउटपुट 'ध्वनि' सही तरीके से करते हैं ... :)

0

मैं अपने स्टीरियो ऑडियो को दो मोनो फ़ाइलों (split stereo audio to mono streams on iOS) में विभाजित करने की कोशिश कर रहा हूं। मैं आपके कोड का उपयोग कर रहा हूं लेकिन इसे काम पर नहीं लग रहा है। आपके सेटअप की सामग्री क्या हैऑडियोऑथफॉर्मैटमोनो विधि?