2011-07-10 37 views
7

我是Objective-C的新手,在iPhone开发中只有5个月的经验。如何在iOS中连接2或3个音频文件?

我需要什么:
我需要连接2个或更多的音频文件合并成一个,并出口结果作为AIFF,MP3,CAF或M4A格式。

例如:含有 “你需要”,第二个 “下载” 和第三部 “文件”
第一个音频文件。
每个音频部分取决于来自用户的操作。

我花了2天没有运气。那个地方是我最后的边界。

我会非常感激的一段代码。

+2

你真的是* *合并,或者你或许意味着*串连*? –

+0

对不起,我英文不好。结果我需要从3个文件“你需要”+“下载”+“文件”中有一个音频文件“你需要下载文件”。我认为正确的词是** concatenate **。 – EEduard

+0

好的 - 我编辑了你的问题,使其更清晰。 –

回答

-1

我有一个想法,不知道它会工作。尝试从这3个文件获取NSData,将数据追加到另一个NSData中,然后写入它。喜欢的东西:

NSMutableData *concatenatedData = [NSMutableData alloc] init]; 
NSData *data1 = [[NSData alloc] initWithContentsOfFile:(NSString *)path]; 
NSData *data2 = [[NSData alloc] initWithContentsOfFile:(NSString *)path]; 
NSData *data3 = [[NSData alloc] initWithContentsOfFile:(NSString *)path]; 
[concatenatedData appendData: data1]; 
[concatenatedData appendData: data2]; 
[concatenatedData appendData: data3]; 
[concatenatedData writeToFile:@"/path/to/concatenatedData.mp3" atomically:YES]; 

这是一个理论我不知道它会工作:)如果我打开用十六进制编辑器的MP3,它的实际工作 - 所有内容复制并粘贴到最后 - 然后我有同样的听起来两次。请尝试一下,让我们知道它是否有效。

+0

** Dimitar Marinov **,谢谢你的回答。我会尽力。无论如何,我会在这里发布结果。再次感谢你的帮助。 – EEduard

+0

不知道你是否成功地用上面的代码做你想要的。这不适用于mp3或m4a音频文件。 –

0

你有没有尝试过这样的事情:

AudioFileCreateWithURL //to create the output file 
For each input file: 
    AudioFileOpenURL //open file 
    repeat 
     AudioFileReadBytes //read from input file 
     AudioFileWriteBytes //write to output file 
    until eof(input file) 
    AudioFileClose //close input file 
AudioFileClose //close output file 

这可能会要求输入文件都是相同的格式,并会造成在同一格式的输出文件。如果您需要转换格式,那么在创建输出文件后可能会更好。

22

下面的代码可用于合并音频文件。

输入文件:要在数组audioIds中提供的文件的ID。例如, audio1.mp3,audio2.mp3 ... audioN.mp3是在文件夹可输出 文件:combined.m4a

 - (BOOL) combineVoices { 

     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]; 

    for (int i = 0; i< [self.audioIds count]; i++) { 
     int key = [[self.audioIds objectAtIndex:i] intValue]; 
     NSString *audioFileName = [NSString stringWithFormat:@"audio%d", key]; 

     //Build the filename with path 
     NSString *soundOne = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp3", audioFileName]]; 
     //NSLog(@"voice file - %@",soundOne); 

     NSURL *url = [NSURL fileURLWithPath:soundOne];  
     AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil]; 
     NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio]; 
     if ([tracks count] == 0) 
      return NO; 
     CMTimeRange timeRangeInAsset = CMTimeRangeMake(kCMTimeZero, [avAsset duration]); 
     AVAssetTrack *clipAudioTrack = [[avAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0]; 
     ok = [compositionAudioTrack insertTimeRange:timeRangeInAsset ofTrack:clipAudioTrack atTime:nextClipStartTime error:&error]; 
     if (!ok) { 
      NSLog(@"Current Video Track Error: %@",error); 
     } 
     nextClipStartTime = CMTimeAdd(nextClipStartTime, timeRangeInAsset.duration); 
    } 

    // create the export session 
    // no need for a retain here, the session will be retained by the 
    // completion handler since it is referenced there 
    AVAssetExportSession *exportSession = [AVAssetExportSession 
              exportSessionWithAsset:composition 
              presetName:AVAssetExportPresetAppleM4A]; 
    if (nil == exportSession) return NO; 

    NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:@"combined.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; 
} 
+0

是否有任何方法将生成的m4a文件转换为mp3文件。 ? –

+0

这工作完美.. Incase,如果你需要改变文件夹结构,只需根据你的需要修改文档目录... –

+0

这一个工作 – commando24

1

你或许应该看看这个帖子做同样的: Combine two audio files into one in objective c

的答案与Dimitar建议的类似。但是你必须记住的两件重要的事情是,首先 - 它只能用于mp3格式,其次你要连接的所有文件的比特率应该是相同的,否则只有你的文件的一部分会在最后的输出中播放。它会在比特率发生变化时停止播放。

SSteve-像Wav文件这样的文件有自己的标题,如果你只是一个接一个地写一个文件,它会播放第一个文件,然后停止播放,尽管文件信息显示更大的文件大小。这是因为我们没有将信息更新到第一个文件的标题中。

3

您可以使用此方法将3个声音合并在一起。

- (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; 


} 
+0

它总是返回AVAssetExportSessionStatusFailed – riddhi

0

我从AVMutableCompositionTrack取了两个不同的mp3文件。并且这两个mp3文件存储在相同的AVMutableComposition中。

当我按下按钮时,控制台会显示新的mp3路径。

-(IBAction)play 
{ 
    [self mixAudio];  
} 

-(void)mixAudio 
{ 
    CFAbsoluteTime currentTime=CFAbsoluteTimeGetCurrent(); 
    AVMutableComposition *composition = [[AVMutableComposition alloc] init]; 

    AVMutableCompositionTrack *compositionAudioTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
    [compositionAudioTrack setPreferredVolume:0.8]; 
    NSString *soundOne =[[NSBundle mainBundle]pathForResource:@"KICK1" ofType:@"mp3"]; 
    NSURL *url = [NSURL fileURLWithPath:soundOne]; 
    AVAsset *avAsset = [AVURLAsset URLAssetWithURL:url options:nil]; 
    NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *clipAudioTrack = [tracks 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.8]; 
    NSString *soundOne1 =[[NSBundle mainBundle]pathForResource:@"KICK2" ofType:@"mp3"]; 
    NSURL *url1 = [NSURL fileURLWithPath:soundOne1]; 
    AVAsset *avAsset1 = [AVURLAsset URLAssetWithURL:url1 options:nil]; 
    NSArray *tracks1 = [avAsset1 tracksWithMediaType:AVMediaTypeAudio]; 
    AVAssetTrack *clipAudioTrack1 = [tracks1 objectAtIndex:0]; 
    [compositionAudioTrack1 insertTimeRange:CMTimeRangeMake(kCMTimeZero, avAsset1.duration) ofTrack:clipAudioTrack1 atTime: kCMTimeZero error:nil]; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); 
    NSString *libraryCachesDirectory = [paths objectAtIndex:0]; 
    NSString *strOutputFilePath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.mov"]; 
    NSString *requiredOutputPath = [libraryCachesDirectory stringByAppendingPathComponent:@"output.m4a"]; 
    NSURL *audioFileOutput = [NSURL fileURLWithPath:requiredOutputPath]; 
    [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL]; 

    AVAssetExportSession *exporter=[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A]; 
    exporter.outputURL=audioFileOutput; 
    exporter.outputFileType=AVFileTypeAppleM4A; 

    [exporter exportAsynchronouslyWithCompletionHandler:^{ 

     NSLog(@" OUtput path is \n %@", requiredOutputPath); 
     NSFileManager * fm = [[NSFileManager alloc] init]; 
     [fm moveItemAtPath:strOutputFilePath toPath:requiredOutputPath error:nil]; 

     NSLog(@" OUtput path is \n %@", requiredOutputPath); 
     NSLog(@"export complete: %lf",CFAbsoluteTimeGetCurrent()-currentTime); 
     NSError *error; 
     audioPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:audioFileOutput error:&error]; 
     audioPlayer.numberOfLoops=0; 
     [audioPlayer play]; 

    }]; 

} 
+0

该怎么做首先运行audio1并在这个音频2播放后 –

+0

这个播放音频1和音频2在一起 –

0

最简单的方法来实现AAC的多种组合:

- (NSString *)concatenatedAACVoicesPath{ 
NSMutableData *concatenatedData = [[NSMutableData alloc] init]; 

NSArray *aacPathArr = [self queryAAC]; 
for (NSString *path in aacPathArr) { 
    NSData *data = [[NSData alloc] initWithContentsOfFile:path]; 
    [concatenatedData appendData: data]; 
} 

NSString *fileNamePath = [NSString stringWithFormat:@"%@/%@.aac",[NSString createPath:currRecordDocName],currRecordDocName]; 
[concatenatedData writeToFile:fileNamePath atomically:YES]; 

return fileNamePath; 

}

+0

我在哪里你的方法定义[self queryAAC]? –