2015-01-18 12 views
0

AVAssetReader을 사용하여 iOS 기기에서 음악에서 샘플을 추출 중입니다.PCM의 이상한 데이터 AVAssetReader의 샘플

18834289801492731920107175936.000000(0x6e736d70) 
somesample 
somesample 
19285086905947468252206596096000.000000(0x7373697a) 

이 두 번호는 (아마도 지난 몇 천 샘플 이내) 트랙의 끝 부분에서 항상, 항상이 겉으로는 정상 찾고 샘플을 각 트랙의 끝 부분, 좀 이상한 데이터를 발생 그들 사이에.

NSURL* url = [now_playing valueForProperty:MPMediaItemPropertyAssetURL]; 
if (url == nil) 
{ 
    // DRM 
    continue; 
} 

AVURLAsset* asset = [AVURLAsset URLAssetWithURL:url options:nil]; 
NSError* error = nil; 
reader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; 

if (error != nil) 
{ 
    NSLog(@"Error initialising AVAssetReader"); 
    NSLog(@"%@", error.localizedDescription); 
    continue; 
} 

AVAssetTrack* track = [asset.tracks objectAtIndex:0]; 

NSDictionary* output_settings = [[NSDictionary alloc] 
    initWithObjectsAndKeys: 

    [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey, 
    [NSNumber numberWithInt:44100], AVSampleRateKey, 
    [NSNumber numberWithInt:1], AVNumberOfChannelsKey, 
    [NSNumber numberWithInt:32], AVLinearPCMBitDepthKey, 
    [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey, 
    [NSNumber numberWithBool:YES], AVLinearPCMIsFloatKey, 
    [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved, nil]; 

reader_output = 
    [[AVAssetReaderTrackOutput alloc] initWithTrack:track 
        outputSettings:output_settings]; 
[reader addOutput:reader_output]; 
[reader startReading]; 

while(true) 
{ 
    CMSampleBufferRef sample_buffer = [reader_output copyNextSampleBuffer]; 
    if (sample_buffer == nil) 
    { 
     continue; 
    } 

    CMBlockBufferRef block_buffer = CMSampleBufferGetDataBuffer(sample_buffer); 

    uint32 block_size = CMBlockBufferGetDataLength(block_buffer); 
    if (block_size > buffer_size) 
    { 
     if (buffer != nullptr) 
     { 
      delete[] buffer; 
      buffer = nullptr; 
     } 

     buffer_size = block_size; 
     buffer = new uint8[buffer_size]; 
    } 

    char* returned_pointer = nullptr; 
    OSStatus status = 
     CMBlockBufferAccessDataBytes(block_buffer, 0, block_size, buffer, &returned_pointer); 
    if (status != kCMBlockBufferNoErr) 
    { 
     NSLog(@"status != kCMBlockBufferNoErr"); 
     break; 
    } 

    uint32 num_floats = buffer_size/sizeof(float); 
    float32* src = reinterpret_cast<float32*>(returned_pointer); 

    float32* dst = &m_data[(m_write_slice * SAMPLES_PER_SLICE) % BUFFER_SIZE]; 

    for (uint32 i = 0; i < num_floats; ++i, ++m_write_index) 
    { 
     m_data[m_write_index] = src[i]; 
    } 

    CFRelease(sample_buffer); 
} 

이 어떻게 든 실수로 읽고 있어요 서명의 어떤 종류가 : 여기

내가 AVAssetReader을 설정하기 위해 작성한 코드입니까?

답변

0

문제가 조금 전에 발견되었습니다. 여기에 답변을 추가하는 것을 잊어 버렸습니다.

// Note here, block_size is the ACTUAL SIZE OF THE BLOCK 
uint32 block_size = CMBlockBufferGetDataLength(block_buffer); 

// And here, buffer_size is the SIZE OF THE BIGGEST BLOCK RECEIVED SO FAR 
if (block_size > buffer_size) 
{ 
    if (buffer != nullptr) 
    { 
     delete[] buffer; 
     buffer = nullptr; 
    } 

    buffer_size = block_size; 
    buffer = new uint8[buffer_size]; 
} 

char* returned_pointer = nullptr; 
OSStatus status = 
    CMBlockBufferAccessDataBytes(block_buffer, 0, block_size, buffer, &returned_pointer); 
if (status != kCMBlockBufferNoErr) 
{ 
    NSLog(@"status != kCMBlockBufferNoErr"); 
    break; 
} 

// THIS IS THE PROBLEM 
// A silly mistake, if the last block is smaller than buffer_size, it will cause the loop 
// below to read too many floats. It should really be 
// uint32 num_floats = block_size/sizeof(float) 
uint32 num_floats = buffer_size/sizeof(float); 
float32* src = reinterpret_cast<float32*>(returned_pointer); 

float32* dst = &m_data[(m_write_slice * SAMPLES_PER_SLICE) % BUFFER_SIZE]; 

for (uint32 i = 0; i < num_floats; ++i, ++m_write_index)