2011-01-07 4 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 오디오를 추출하는 데 사용하는 코드입니다 또는 뭔가 ...

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 양방향이 t depth는 각 샘플이 2 바이트를 차지한다는 것을 의미합니다. 이는 왼쪽 채널 데이터가 바이트 {0,1}, {4,5}, {8,9} 등으로되어 있음을 의미합니다. 인터리브 된 것은 샘플이 인터리브 된 것이지 바이트가 아니라는 것을 의미합니다. 그 외의 다른 방법을 시도해보고 코드에 문제가 있는지 확인하십시오.

또한 오디오 채널을 추출 후, 설정해야 16 비트 깊이 1 개 채널로서 상기 추출 된 채널의 포맷?

추출 후 두 채널 중 하나만 남아 있으므로 예. 올바른 것입니다.

+0

좋아, 내가 실제로 시도한 결과가 옳지 않다 ... 내가 말한 것처럼 추출 알고리즘을 사용했지만 출력이 왜곡 된 것처럼 들린다. 왜곡되었지만 "느리다"... – Samuel

+0

코드 내가 언급 한 알고리즘에 사용 된 것은 내 게시물에 담겨있다. 내가 잘못 입력 한 원인이 무엇이든 환영합니다. – Samuel

+0

입력 샘플 속도가 44100입니까? "느린"재생을 설명 할 수있는 하나의 잘못이 있다면 – BrokenGlass

1

오디오가 '느리게'소리가 나는 것과 비슷한 오류가 발생했습니다. 그 이유는 mChannelsPerFrame을 1로 지정했기 때문입니다. 단, 이중 채널 사운드가있는 것입니다. 2로 설정하면 재생 속도가 빨라집니다. 또한이 작업을 수행 한 후에 올바르게 '소리'를 들려 주는지 알려주십시오. :)

0

스테레오 오디오를 두 개의 모노 파일 (split stereo audio to mono streams on iOS)로 분할하려고합니다. 나는 당신의 코드를 사용해 왔지만 작동시키지 못하고있다. setupAudioWithFormatMono 메서드의 내용은 무엇입니까?

관련 문제