2011-12-26 14 views
14

Voglio avere due file audio e mixarlo e riprodurlo a livello di programmazione. Quando sto riproducendo il primo file audio, dopo un po 'di tempo (tempo dinamico) ho bisogno di aggiungere il secondo piccolo file audio con il primo file audio quando è in corso qualche parte del primo file audio, quindi finalmente ho bisogno di salvare come un audio file sul dispositivo. Dovrebbe riprodurre il file audio con l'audio del mixer che ho incluso il secondo.iPhone: mixa due file audio a livello di programmazione?

Ho attraversato molti forum, ma non sono riuscito a capire esattamente come ottenere questo risultato?

Qualcuno potrebbe, per favore, chiarire i miei dubbi di sotto?

  1. In questo caso, quale file audio/formato dovrei usare? Posso usare i file .avi?
  2. Come aggiungere il secondo audio dopo l'ora dinamica impostata sul primo file audio a livello di programmazione? Ad esempio: se il primo tempo totale dell'audio è di 2 minuti, potrebbe essere necessario mixare il secondo file audio (audio di 3 secondi) da qualche parte in 1 minuto o 1,5 minuti o 55 secondi del primo file. La sua dinamica.
  3. Come salvare il file audio di output finale sul dispositivo? Se salvi il file audio in modo programmatico da qualche parte, posso riprodurre di nuovo?

Non so come raggiungerlo. Si prega di suggerire i vostri pensieri!

+0

no non è possibile salvarlo come .avi perché un avi è solo un contenitore (e può contenere video pure). Non sono sicuro di cosa devi usare sul dispositivo iOS, ma suppongo che dovrai scrivere un documento wav (in altre parole, picchi/onde audio puri). Per combinare quelli hai bisogno di una conoscenza avanzata di lavorare con l'audio che non ho. E quindi non sono in grado di dire qualcosa di informativo a riguardo. –

+0

http://developer.apple.com/library/ios/#codinghowtos/AudioAndVideo/_index.html –

risposta

0

Se si intende riprodurre più suoni contemporaneamente, utilizzare decisamente il formato * .caf. Apple lo consiglia per la riproduzione di più suoni contemporaneamente. In termini di missaggio programmatico, presumo che tu voglia solo che suonino allo stesso tempo. Mentre suona un suono, dì all'altro suono di suonare in qualsiasi momento desideri. Per impostare un'ora specifica, utilizzare NSTimer (NSTimer Class Reference) e creare un metodo per far riprodurre l'audio quando scatta il timer.

6
  • Aprire ogni file audio
  • leggere le informazioni di intestazione
  • ottenere audio non compresso grezzo nella memoria come un array di int per ogni file
  • Partendo dal punto di matrice del file 1 di cui si desidera mescolare in file2, loop through, aggiungendo il valore int di file2 a file1, assicurandosi di "ritagliare" qualsiasi valore sopra o sotto il massimo (questo è il modo in cui si mischia l'audio ... sì, è quello semplice). Se file2 è più lungo, dovrai rendere il primo array abbastanza lungo da contenere completamente il resto di file2.
  • Scrivi nuove informazioni di intestazione e quindi l'audio dall'array a cui hai aggiunto file2.
  • Se è presente una compressione o i file non si adattano alla memoria, potrebbe essere necessario implementare uno schema di buffer più complesso.
+0

Semplicemente aggiungendo i due flussi insieme e il ritaglio a valori estremi non suona (nessun gioco di parole) come si comporterebbe molto uscita utile I due "input" devono essere adattati in modo appropriato in modo tale che non si debba verificare alcun troncamento. –

+0

Sì, è essenzialmente così. Speriamo che i due file siano nello stesso formato, alla stessa frequenza di campionamento e non compressi, quindi è una questione "semplice" di aggiunta di array (tenendo presente che ci sono probabilmente due canali). Una prima scansione dei dati rivelerebbe se il ritaglio si sarebbe verificato, e quindi il ridimensionamento potrebbe essere applicato per mantenere il volume ottimale evitando il clipping. –

+0

@Sedate - Hai assolutamente ragione! Ma se ripensi ai tuoi giorni di band del garage con un mixer analogico usato, ricorderai la sfortunata verità - è così che è nel mondo reale. I suoni sono mescolati senza ridimensionamento; quando i livelli sono eccessivi, la distorsione risultante viene in realtà chiamata "ritaglio". La tecnica menzionata da Hot Licks si chiama 'compressione' (sebbene sia un'implementazione niave) e per analogico, è un'altra scatola da buttare nel rack. Di solito, però, sorprendentemente, il risultato non si ritaglia. Provalo in Audacity (fai una copia installata, non è così ;-) – FastAl

2

In questo caso, quale file audio/formato dovrei usare? Posso usare i file .avi?

È possibile scegliere un formato compresso o non compresso. I formati comuni non compressi includono Wav e AIFF. CAF può rappresentare dati compressi e non compressi. .avi non è un'opzione (offerta dal sistema operativo).

Se i file sono grandi e lo spazio di archiviazione (su disco) è un problema, è possibile considerare il formato AAC salvato in un CAF (o semplicemente .m4a).Per la maggior parte delle applicazioni, i campioni a 16 bit saranno sufficienti e si può anche risparmiare spazio, memoria e CPU salvando questi file ad una frequenza di campionamento appropriata (rif: i CD sono 44.1kHz).

Poiché l'interfaccia ExtAudioFile estrae il processo di conversione, non è necessario modificare il programma per confrontare le dimensioni e le differenze di velocità dei formati compressi e non compressi per la distribuzione (AAC in CAF andrebbe bene per le normali applicazioni).

L'audio di qualità CD non compresso consuma circa 5,3 MB al minuto, per canale. Pertanto, se si dispone di 2 file audio stereo, ciascuno di 3 minuti e un buffer di destinazione di 3 minuti, i requisiti di memoria saranno di circa 50 MB.

Poiché si dispone di "minuti" di audio, potrebbe essere necessario evitare di caricare tutti i dati audio in memoria contemporaneamente. Per leggere, manipolare e combinare l'audio, avrete bisogno di una rappresentazione non compressa con cui lavorare in memoria, quindi i formati di compressione non sono d'aiuto. Inoltre, la conversione di una rappresentazione compressa in pcm richiede una buona quantità di risorse; la lettura di un file compresso, sebbene con meno byte, può richiedere più (o meno) tempo.

Come aggiungere il secondo audio dopo l'ora dinamica impostata sul primo file audio a livello di programmazione? Ad esempio: se il primo tempo totale dell'audio è di 2 minuti, potrebbe essere necessario mixare il secondo file audio (audio di 3 secondi) da qualche parte in 1 minuto o 1,5 minuti o 55 secondi del primo file. La sua dinamica.

per leggere i file e convertirli nel formato che si desidera utilizzare, utilizzare le API ExtAudioFile - questo convertirà nel formato campione destinazione per voi. Le comuni rappresentazioni campione PCM in memoria includono SInt32, SInt16 e float, ma possono variare in modo selvaggio in base all'applicazione e all'hardware (oltre a iOS). Le API ExtAudioFile converte anche i formati compressi in PCM, se necessario.

I file audio di input devono avere la stessa frequenza di campionamento. In caso contrario, sarà necessario ricampionare l'audio, un processo complesso che richiede anche molte risorse (se eseguite correttamente/accuratamente). Se devi supportare il ricampionamento, raddoppia il tempo che hai assegnato per completare questa attività (non descrivendo qui il processo).

Per aggiungere i suoni, è necessario richiedere campioni PCM dai file, elaborare e scrivere sul file di output (o buffer in memoria).

Per determinare quando aggiungere gli altri suoni, è necessario ottenere le frequenze di campionamento per i file di input (tramite ExtAudioFileGetProperty). Se vuoi scrivere il secondo suono nel buffer di destinazione a 55 secondi, inizi ad aggiungere i suoni al numero di campione SampleRate * 55, dove SampleRate è la frequenza di campionamento dei file che stai leggendo.

Per miscelare l'audio, sarà solo utilizzare questo modulo (pseudocodice):

mixed[i] = fileA[i] + fileB[i]; 

ma bisogna essere sicuri di evitare un eccesso/underflow e altri errori aritmetici. In genere, si esegue questo processo utilizzando un valore intero, poiché i calcoli in virgola mobile possono richiedere molto tempo (quando ce ne sono così tanti). Per alcune applicazioni, puoi semplicemente spostare e aggiungere senza preoccuparti di un overflow: questo ridurrebbe in modo efficace ogni input di una metà prima di aggiungerli. L'ampiezza del risultato sarebbe la metà. Se hai il controllo sul contenuto dei file (ad es. Sono tutti raggruppati come risorse), puoi semplicemente assicurarti che nessun campione di picco nei file superi la metà del valore di fondo scala (circa -6dBFS). Ovviamente, il salvataggio come float risolverebbe questo problema a scapito dell'introduzione di richieste di I/o di CPU, memoria e file più elevate.

A questo punto, avresti 2 file aperti per la lettura e uno aperto per la scrittura, quindi alcuni piccoli buffer temporanei per l'elaborazione e il missaggio degli input prima di scrivere nel file di output. È necessario eseguire queste richieste in blocchi per l'efficienza (ad esempio, leggere 1024 campioni da ciascun file, elaborare i campioni, scrivere 1024 campioni). Le API non garantiscono molto per quanto riguarda la memorizzazione nella cache e il buffering per l'efficienza.

Come salvare il file audio di output finale sul dispositivo? Se salvi il file audio in modo programmatico da qualche parte, posso riprodurre di nuovo?

Le API ExtAudioFile potrebbero funzionare per le tue esigenze di lettura e scrittura. Sì, puoi leggerlo/riprodurlo più tardi.

2

Ciao È possibile farlo utilizzando av fondazione

- (BOOL) combineVoices1 
{ 
    NSError *error = nil; 
    BOOL ok = NO; 


    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 


    CMTime nextClipStartTime = kCMTimeZero; 
    //Create AVMutableComposition Object.This object will hold our multiple AVMutableCompositionTrack. 
    AVMutableComposition *composition = [[AVMutableComposition alloc] init]; 

    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [compositionAudioTrack setPreferredVolume:0.8]; 
    NSString *soundOne =[[NSBundle mainBundle]pathForResource:@"test1" ofType:@"caf"]; 
    NSURL *url = [NSURL fileURLWithPath:soundOne]; 
    AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil]; 
    NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
    [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack atTime:kCMTimeZero error:nil]; 

    AVMutableCompositionTrack *compositionAudioTrack1 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [compositionAudioTrack setPreferredVolume:0.3]; 
    NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"test" ofType:@"caf"]; 
    NSURL *url1 = [NSURL fileURLWithPath:soundOne1]; 
    AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil]; 
    NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *clipAudioTrack1 = [[avAsset1 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
    [compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset.duration) ofTrack:clipAudioTrack1 atTime:kCMTimeZero error:nil]; 


    AVMutableCompositionTrack *compositionAudioTrack2 = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [compositionAudioTrack2 setPreferredVolume:1.0]; 
    NSString *soundOne2 =[[NSBundle mainBundle]pathForResource:@"song" ofType:@"caf"]; 
    NSURL *url2 = [NSURL fileURLWithPath:soundOne2]; 
    AVAsset *avAsset2 = [AVURLAsset URLAssetWithURL:url2 options:nil]; 
    NSArray *tracks2 = [avAsset2 tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *clipAudioTrack2 = [[avAsset2 tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
    [compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset2.duration) ofTrack:clipAudioTrack2 atTime:kCMTimeZero error:nil]; 



    AVAssetExportSession *exportSession = [AVAssetExportSession 
              exportSessionWithAsset:composition 
              presetName:AVAssetExportPresetAppleM4A]; 
    if (nil == exportSession) return NO; 

    NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:@"combined10.m4a"]; 
    //NSLog(@"Output file path - %@",soundOneNew); 

    // configure export session output with all our parameters 
    exportSession.outputURL = [NSURL fileURLWithPath:soundOneNew]; // output path 
    exportSession.outputFileType = AVFileTypeAppleM4A; // output file type 

    // perform the export 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 

     if (AVAssetExportSessionStatusCompleted == exportSession.status) { 
      NSLog(@"AVAssetExportSessionStatusCompleted"); 
     } else if (AVAssetExportSessionStatusFailed == exportSession.status) { 
      // a failure may happen because of an event out of your control 
      // for example, an interruption like a phone call comming in 
      // make sure and handle this case appropriately 
      NSLog(@"AVAssetExportSessionStatusFailed"); 
     } else { 
      NSLog(@"Export Session Status: %d", exportSession.status); 
     } 
    }]; 


    return YES; 


} 
Problemi correlati