2011-07-10 6 views
7

Tôi là người mới trong Mục tiêu-C và có kinh nghiệm chỉ trong 5 tháng phát triển iPhone.Làm cách nào để ghép nối 2 hoặc 3 tệp âm thanh trong iOS?

Những gì tôi cần:
tôi cần phải nối 2 hoặc nhiều file audio thành một, và kết quả xuất khẩu như aiff, mp3, caf hoặc định dạng m4a.

Ví dụ:
tập tin âm thanh đầu tiên có chứa "Bạn cần", thứ hai "download" và "tài liệu" thứ ba.
Mọi phần âm thanh đều phụ thuộc vào hành động của người dùng.

Tôi đã dành 2 ngày mà không gặp may. Nơi đó là biên giới cuối cùng của tôi.

Tôi sẽ đánh giá cao một đoạn mã.

+2

Bạn có thực sự có nghĩa là * merge *, hay bạn có thể có nghĩa là * concatenate *? –

+0

Xin lỗi vì tiếng Anh không tốt của tôi. Tôi cần kết quả có một tệp âm thanh "Bạn cần tải xuống tài liệu" từ 3 tệp "Bạn cần" + "tải xuống" + "tài liệu". Tôi nghĩ từ đúng là ** nối **. – EEduard

+0

OK - Tôi đã chỉnh sửa câu hỏi của bạn để làm cho nó rõ ràng hơn. –

Trả lời

-1

Tôi có một ý tưởng, không chắc chắn nó sẽ hoạt động. Cố gắng lấy NSData từ 3 tệp này, thêm dữ liệu vào NSData khác và sau đó viết nó. Một cái gì đó như:

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

Đó là lý thuyết tôi không chắc chắn nó sẽ hoạt động :), nó thực sự hoạt động nếu tôi mở một mp3 với trình chỉnh sửa hex - sao chép mọi thứ và dán nó vào cuối - sau đó tôi có cùng âm thanh hai lần. Hãy thử nó và cho chúng tôi biết nếu nó hoạt động.

+0

** Dimitar Marinov **, cảm ơn bạn đã trả lời. Tôi sẽ thử. Tôi sẽ đăng ở đây kết quả dù sao có giúp được điều đó hay không. Cảm ơn một lần nữa vì sự giúp đỡ của bạn. – EEduard

+0

Không chắc chắn nếu bạn đã thành công trong việc làm những gì bạn muốn với mã trên. Tính năng này không hoạt động đối với các tệp âm thanh mp3 hoặc m4a. –

0

Các bạn đã thử một cái gì đó như thế này:

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 

Điều này có lẽ sẽ đòi hỏi rằng các tập tin đầu vào là tất cả các định dạng tương tự và sẽ tạo ra các tập tin đầu ra ở định dạng đó tương tự. Nếu bạn cần chuyển đổi định dạng, điều đó có thể được thực hiện tốt hơn sau khi tạo tệp đầu ra.

22

Mã bên dưới có thể được sử dụng để hợp nhất các tệp âm thanh.

Tệp đầu vào: Id của tệp được cung cấp trong mảng audioIds. Ví dụ: audio1.mp3, audio2.mp3 ... audioN.mp3 sẽ có sẵn trong các tài liệu thư mục tập tin đầu ra: 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

là có cách nào để chuyển đổi tập tin m4a kết quả thành tập tin mp3. ? –

+0

Điều này hoạt động hoàn hảo .. Nếu bạn cần thay đổi cấu trúc thư mục, chỉ cần sửa đổi thư mục tài liệu theo nhu cầu của bạn ... –

+0

cái này đang hoạt động – commando24

1

Bạn có lẽ nên nhìn vào bài này để làm giống nhau: Combine two audio files into one in objective c

Các câu trả lời tương tự như những gì Dimitar đã gợi ý. Nhưng 2 điều quan trọng mà bạn phải ghi nhớ là, đầu tiên - nó chỉ hoạt động với định dạng mp3 và thứ hai tốc độ bit của tất cả các tệp mà bạn đang cố gắng ghép nối phải giống nhau hoặc chỉ các phần khác trong tệp của bạn chơi ở đầu ra cuối cùng. Nó sẽ ngừng phát khi thay đổi tốc độ bit.

SSteve- Các tệp như tệp Wav có tiêu đề của riêng chúng và nếu bạn chỉ ghi một tệp, sau đó sẽ chỉ phát tệp đầu tiên và sau đó dừng phát, kiểm tra thông tin tệp hiển thị kích thước tệp lớn hơn. điều này là bởi vì chúng tôi không có thông tin cập nhật vào tiêu đề của tập tin đầu tiên.

3

Bạn có thể sử dụng phương pháp này để hợp nhất 3 âm thanh với nhau.

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

nó trả về luôn luôn AVAssetExportSessionStatusFailed – riddhi

0

Tôi đã lấy hai tệp mp3 khác nhau từ AVMutableCompositionTrack. và hai tệp mp3 này được lưu trữ trong cùng một AVMutableComposition.

khi tôi sẽ nhấn nút đường dẫn của mp3 mới sẽ được hiển thị bằng bảng điều khiển.

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

phải làm gì để chạy audio1 trước và sau âm thanh này 2 phát –

+0

âm thanh phát 1 và âm thanh 2 này với nhau –

0

Cách dễ nhất để thực hiện nhiều sự kết hợp của 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

Tôi định nghĩa phương thức của mình ở [queryAAC] ở đâu? –