简体   繁体   English

iOS:如何从.aif录音的开头和结尾修剪沉默?

[英]iOS: How to trim silence from start and end of .aif audio recording?

My app includes the ability for the user to record a brief message; 我的应用程序包括用户记录简短消息的能力; I'd like to trim off any silence (or, to be more precise, any audio whose volume falls below a given threshold) from the beginning and end of the recording. 我想从录制的开始和结束中删除任何静音(或者更确切地说,任何音量低于给定阈值的音频)。

I'm recording the audio with an AVAudioRecorder, and saving it to an .aif file. 我正在使用AVAudioRecorder录制音频,并将其保存为.aif文件。 I've seen some mention elsewhere of methods by which I could have it wait to start recording until the audio level reaches a threshold; 我已经在其他地方看到了一些方法,我可以让它等待开始录音直到音频电平达到阈值; that'd get me halfway there, but won't help with trimming silence off the end. 那会让我走到一半,但最终无法帮助修剪沉默。

If there's a simple way to do this, I'll be eternally grateful! 如果有一个简单的方法可以做到这一点,我将永远感激不尽!

Thanks. 谢谢。

This project takes audio from the microphone, triggers on loud noise and untriggers when quiet. 该项目从麦克风接收音频,在嘈杂时触发,在安静时触发非触发。 It also trims and fades in/fades out around the ends. 它还会在两端修剪和淡入/淡出。

https://github.com/fulldecent/FDSoundActivatedRecorder https://github.com/fulldecent/FDSoundActivatedRecorder

Relevant code you are seeking: 您正在寻找的相关代码:

- (NSString *)recordedFilePath
{
    // Prepare output
    NSString *trimmedAudioFileBaseName = [NSString stringWithFormat:@"recordingConverted%x.caf", arc4random()];
    NSString *trimmedAudioFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:trimmedAudioFileBaseName];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:trimmedAudioFilePath]) {
        NSError *error;
        if ([fileManager removeItemAtPath:trimmedAudioFilePath error:&error] == NO) {
            NSLog(@"removeItemAtPath %@ error:%@", trimmedAudioFilePath, error);
        }
    }
    NSLog(@"Saving to %@", trimmedAudioFilePath);

    AVAsset *avAsset = [AVAsset assetWithURL:self.audioRecorder.url];
    NSArray *tracks = [avAsset tracksWithMediaType:AVMediaTypeAudio];
    AVAssetTrack *track = [tracks objectAtIndex:0];

    AVAssetExportSession *exportSession = [AVAssetExportSession
                                           exportSessionWithAsset:avAsset
                                           presetName:AVAssetExportPresetAppleM4A];

    // create trim time range
    CMTime startTime = CMTimeMake(self.recordingBeginTime*SAVING_SAMPLES_PER_SECOND, SAVING_SAMPLES_PER_SECOND);
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, kCMTimePositiveInfinity);

    // create fade in time range
    CMTime startFadeInTime = startTime;
    CMTime endFadeInTime = CMTimeMake(self.recordingBeginTime*SAVING_SAMPLES_PER_SECOND + RISE_TRIGGER_INTERVALS*INTERVAL_SECONDS*SAVING_SAMPLES_PER_SECOND, SAVING_SAMPLES_PER_SECOND);
    CMTimeRange fadeInTimeRange = CMTimeRangeFromTimeToTime(startFadeInTime, endFadeInTime);

    // setup audio mix
    AVMutableAudioMix *exportAudioMix = [AVMutableAudioMix audioMix];
    AVMutableAudioMixInputParameters *exportAudioMixInputParameters =
    [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:track];

    [exportAudioMixInputParameters setVolumeRampFromStartVolume:0.0 toEndVolume:1.0
                                                      timeRange:fadeInTimeRange];
    exportAudioMix.inputParameters = [NSArray
                                      arrayWithObject:exportAudioMixInputParameters];

    // configure export session  output with all our parameters
    exportSession.outputURL = [NSURL fileURLWithPath:trimmedAudioFilePath];
    exportSession.outputFileType = AVFileTypeAppleM4A;
    exportSession.timeRange = exportTimeRange;
    exportSession.audioMix = exportAudioMix;

    // MAKE THE EXPORT SYNCHRONOUS
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [exportSession exportAsynchronouslyWithCompletionHandler:^{
        dispatch_semaphore_signal(semaphore);
    }];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    if (AVAssetExportSessionStatusCompleted == exportSession.status) {
        NSLog(@"AVAssetExportSessionStatusCompleted");
        return trimmedAudioFilePath;
    } 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 %@", exportSession.error.localizedDescription);
    } else {
        NSLog(@"Export Session Status: %d", exportSession.status);
    }
    return nil;
}

I'm recording the audio with an AVAudioRecorder, and saving it to an .aif file. 我正在使用AVAudioRecorder录制音频,并将其保存为.aif文件。 I've seen some mention elsewhere of methods by which I could have it wait to start recording until the audio level reaches a threshold; 我已经在其他地方看到了一些方法,我可以让它等待开始录音直到音频电平达到阈值; that'd get me halfway there 那让我走到一半

Without adequate buffering, that would truncate the start. 如果没有足够的缓冲,那将会缩短开始时间。

I don't know of an easy way. 我不知道一个简单的方法。 You would have to write a new audio file after recording and analyzing it for the desired start and end points. 在录制和分析所需的起点和终点后,您必须编写新的音频文件。 Modifying the existing file would be straightforward if you knew the AIFF format well (not many people do) and had an easy way to read the file's sample data. 如果你很好地了解AIFF格式(不是很多人)并且有一种简单的方法来读取文件的样本数据,那么修改现有文件会很简单。

The analysis stage is pretty easy for a basic implementation -- evaluate the average power of sample data, until your threshold is exceeded. 对于基本实现,分析阶段非常简单 - 评估样本数据的平均功效,直到超过阈值。 Repeat in reverse for end. 反复重复以结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM