2012-05-07 24 views
7

Ses Birimlerini kullanarak bir müzik kayıt uygulaması kodluyorum ve sonuçta elde edilen M4A dosyamın çok müthiş bir gürültüden başka bir şey çalmasını sağladığım bazı sorunlar yaşıyorum . Bu SO sourcesasreferences'u kullandım ve sorunları gidermek için her şeyi denedim.Dosyaya uzak I/0 çıkışı yazma ve kodlama - Temel Ses

2 düğümlü bir AUGraph var: çok kanallı bir mikser ve uzak bir G/Ç. Mikserinde iki giriş geri çağırma var: mikrofondan girişi çeken ve ses dosyasından çekilen bir. Mikser çıkışı, I/O ünitesindeki çıkış kapsamının giriş elemanına bağlanır. Bu eşzamanlı G/Ç'yi etkinleştirir.

ben ekledim çıktı bir geri arama ve iki yöntem yakalamak için:

geri arama

static OSStatus recordAndSaveCallback (void *    inRefCon, 
             AudioUnitRenderActionFlags * ioActionFlags, 
             const AudioTimeStamp *  inTimeStamp, 
             UInt32      inBusNumber, 
             UInt32      inNumberFrames, 
             AudioBufferList *   ioData) 
{ 
    Mixer* THIS = (__bridge Mixer*)inRefCon; 
    AudioBufferList bufferList; 

    OSStatus status; 
    status = AudioUnitRender(THIS.ioUnit,  
          ioActionFlags, 
          inTimeStamp, 
          0, 
          inNumberFrames, 
          &bufferList); 

    SInt16 samples[inNumberFrames]; // A large enough size to not have to worry about buffer overrun 
    memset (&samples, 0, sizeof (samples)); 

    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0].mData = samples; 
    bufferList.mBuffers[0].mNumberChannels = 1; 
    bufferList.mBuffers[0].mDataByteSize = inNumberFrames*sizeof(SInt16); 

    OSStatus result; 
    if (*ioActionFlags == kAudioUnitRenderAction_PostRender) { 
     result = ExtAudioFileWriteAsync(THIS.extAudioFileRef, inNumberFrames, &bufferList); 
     if(result) printf("ExtAudioFileWriteAsync %ld \n", result);} 
    return noErr; 
} 

Kayıt Yöntemi:

- (void)recordFile 
{  
    OSStatus result; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"]; 

    CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, 
                  (__bridge CFStringRef)recordFile, 
                  kCFURLPOSIXPathStyle, 
                  false);  

    AudioStreamBasicDescription destinationFormat; 
    memset(&destinationFormat, 0, sizeof(destinationFormat)); 
    destinationFormat.mChannelsPerFrame = 1; 
    destinationFormat.mFormatID = kAudioFormatMPEG4AAC; 
    UInt32 size = sizeof(destinationFormat); 
    result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);   
    if(result) printf("AudioFormatGetProperty %ld \n", result);  


    result = ExtAudioFileCreateWithURL(destinationURL, 
             kAudioFileM4AType, 
             &destinationFormat, 
             NULL, 
             kAudioFileFlags_EraseFile, 
             &extAudioFileRef); 
    if(result) printf("ExtAudioFileCreateWithURL %ld \n", result); 


    AudioStreamBasicDescription clientFormat; 
    memset(&clientFormat, 0, sizeof(clientFormat)); 


    UInt32 clientsize = sizeof(clientFormat); 
    result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &clientsize); 
    if(result) printf("AudioUnitGetProperty %ld \n", result); 

    UInt32 codec = kAppleHardwareAudioCodecManufacturer; 

    result = ExtAudioFileSetProperty(extAudioFileRef, 
            kExtAudioFileProperty_CodecManufacturer, 
            sizeof(codec), 
            &codec); 

    if(result) printf("ExtAudioFileSetProperty %ld \n", result); 


    result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat), &clientFormat); 
    if(result) printf("ExtAudioFileSetProperty %ld \n", result); 


    result = ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL); 
    if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];} 

    result = AudioUnitAddRenderNotify(ioUnit, recordAndSaveCallback, (__bridge void*)self); 
    if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}  
} 

Tasarruf Yöntemi:

- (void) saveFile { 
    OSStatus status = ExtAudioFileDispose(extAudioFileRef); 
    NSLog(@"OSStatus(ExtAudioFileDispose): %ld\n", status); 

} 

Bubenim konsolunda gördükleri şeydir:

Stopping audio processing graph 
OSStatus(ExtAudioFileDispose): 0 
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 

Benim kod bu işe aldık insanların buna çok benzer geliyor bana, ama açıkça ben ettik önemli bir hata yaptı. Eminim bununla mücadele eden başkaları olmalı.

Herhangi bir fikir sahibi olan var mı?

Teşekkürler.

+0

'recordAndSaveCallback' bitmeden' ​​'saveFile' yönteminin çağrıldığını görüyoruz. SaveFile çağrılmadan önce AUGraph'ı mı durdunuz? – sbooth

+0

grafiğinizle ilgili herhangi bir sorunu göz ardı etmek için bir deneme olarak, wav gibi daha basit bir format kullanarak denemek ve kaydetmek için iyi bir fikir olabilir. ASBD'nin doğru olması zor olabilir, ancak ASBD'nin (benim fikrim) bir problem olduğunu tespit ederseniz, en azından dosya formatını denemeye odaklanabilirsiniz. – dubbeat

+0

macerror -50'nin komut satırından çalıştırılması şunu verir: Mac OS hatası -50 (paramErr): kullanıcı parametre listesinde hata – morgancodes

cevap

1

Sorunun uzun zaman önce sorulmuş olduğunu biliyorum ve muhtemelen şu anda hatayı öğrendiniz, sadece aynı sorunu yaşayabilecek başkalarına cevap veriyorum.

Yanlış olabilirim ama sorunun arabellek için değişken bir değişken beyanı yaptığınız gerçeğinden kaynaklandığını düşünüyorum.

Ben değiştirmek öneririm

SInt16 samples[inNumberFrames]; 

recordAndSaveCallback Eğer bir in-kapsam beyanı yaparsanız, verileri olarak yok edilecek, tampon listesini doldurmak için düşünüldüğünden

SInt16* samples = malloc(inNumberFrames * sizeof(SInt16)); 

içine kapsam biter bitmez.