2015-10-26 6 views
0

Может ли кто-нибудь помочь мне удалить первоначальную тишину в записанном аудио-файле?Удалить начальную тишину из записанного аудиофайла типа волны

Я извлекаю байты данных из wav-файла и после игнорирования первых 44 байтов заголовков, получающих конечный диапазон 0 байтов, которые молчат в волновом файле.

После этого из общих байт данных, конечного диапазона тихих звуковых байтов и общей продолжительности файла, я вычисляю время молчания аудиофайла и обрезаю это много времени из аудиофайла.

Но проблема в том, что в звуковом файле остается какая-то тихая часть.

Не уверен, что я что-то пропустил?

- (double)processAudio:(float)totalFileDuration withFilePathURL:(NSURL *)filePathURL{ 
    NSMutableData *data = [NSMutableData dataWithContentsOfURL:filePathURL]; 
    NSMutableData *Wave1= [NSMutableData dataWithData:[data subdataWithRange:NSMakeRange(44, [data length] - 44)]]; 
    uint8_t * bytePtr = (uint8_t *)[Wave1 bytes] ; 
    NSInteger totalData = [Wave1 length]/sizeof(uint8_t); 
    int endRange = 0; 
    for (int i = 0 ; i < totalData; i ++){ 
     /
     if (bytePtr[i] == 0) { 
      endRange = i; 
     }else 
      break; 
    } 

    double silentAudioDuration =(((float)endRange/(float)totalData)*totalFileDuration); 
    return silentAudioDuration; 
} 
- (void)trimAudioFileWithInputFilePath :(NSString *)inputPath toOutputFilePath : (NSString *)outputPath{ 
    /
    NSString *strInputFilePath = inputPath; 
    NSURL *audioFileInput = [NSURL fileURLWithPath:strInputFilePath]; 

    /
    NSString *strOutputFilePath = [outputPath stringByDeletingPathExtension]; 
    strOutputFilePath = [strOutputFilePath stringByAppendingString:@".m4a"]; 
    NSURL *audioFileOutput = [NSURL fileURLWithPath:strOutputFilePath]; 
    newPath = strOutputFilePath; 

    if (!audioFileInput || !audioFileOutput){ 
     /
    } 

    [[NSFileManager defaultManager] removeItemAtURL:audioFileOutput error:NULL]; 
    AVAsset *asset = [AVAsset assetWithURL:audioFileInput]; 
    CMTime audioDuration = asset.duration; 
    float audioDurationSeconds = CMTimeGetSeconds(audioDuration); 

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

    if (exportSession == nil){ 
     /
    } 

    /
    float startTrimTime = [self processAudio:audioDurationSeconds withFilePathURL:audioFileInput]; 
    /
    /
    float endTrimTime = audioDurationSeconds; 

    recordingDuration = audioDurationSeconds - startTrimTime; 

    CMTime startTime = CMTimeMake((int)(floor(startTrimTime * 100)), 100); 
    CMTime stopTime = CMTimeMake((int)(ceil(endTrimTime * 100)), 100); 
    CMTimeRange exportTimeRange = CMTimeRangeFromTimeToTime(startTime, stopTime); 

    exportSession.outputURL = audioFileOutput; 
    exportSession.outputFileType = AVFileTypeAppleM4A; 
    exportSession.timeRange = exportTimeRange; 

    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
     if (AVAssetExportSessionStatusCompleted == exportSession.status){ 
     } 
     else if (AVAssetExportSessionStatusFailed == exportSession.status){ 
     } 
    }]; 
} 

Что я здесь делаю неправильно?

ответ

0

Возможно, у вас нет полной тишины в ваших файлах? Возможно, ваш образец имеет значение 1 или 2 или 3, что технически не тикает, но очень тихо.

Волновые файлы хранятся в виде подписанных номеров, если 16 бит и без знака, если 8 бит. Вы обрабатываете и заставляете свои данные быть неподписанным байтом: uint8_t * bytePtr = (uint8_t *) [Wave1 bytes];

Вам необходимо знать формат вашего волнового файла, который можно получить из заголовка. (Это может использовать размер выборки, скажем, 8 бит, 16 бит, 24 бит, и т.д.)

Если это 16 бит и моно, вам нужно использовать:

int16_t * ptr = (int16_t) [Wave1 bytes]; 

Ваш цикл подсчитывает один байт в время, поэтому вам нужно будет настроить его для увеличения размера вашего кадра.

Вы также не считаете моно/стерео.
В общем, ваша функция processAudio нуждается в более подробной информации и должна учитывать количество каналов на кадр (стерео/моно) и размер образца.

Вот заголовок волны с типами iOS. Вы можете передать первые 44 байта и получить данные заголовка, чтобы вы знали, с чем имеете дело.

typedef struct waveHeader_t 
{ 
    //RIFF 
    char  chunkID[4];    ///< Should always contain "RIFF" BigEndian //4 
    uint32_t chunkSize;    ///< total file length minus 8 (little endian!!!) //4 
    char  format[4];    ///< should be "WAVE" Big Endian 

    // fmt 
    char  subChunk1ID[4];   ///< "fmt " Big Endian    //4 
    uint32_t subChunk1Size;   ///< 16 for PCM format      //2 
    uint16_t audioFormat;   ///< 1 for PCM format      //2 
    uint16_t numChannels;   ///< channels          //2 
    uint32_t sampleRate;    ///< sampling frequency       //4 
    uint32_t byteRate;    ///< samplerate * numchannels * bitsperSample/8 
    uint16_t blockAlign;    ///< frame size 
    uint16_t bitsPerSample;   ///< bits per Sample 

    char  subChunk2ID[4];   ///< should always contain "data" 
    uint32_t subChunk2Size;   ///< 

    ///< sample data follows this..... 
} waveHeader_t; 

Так что ваш список дел является

  • Извлечение полей из заголовка
  • В частности получить количество каналов и бит на канал (примечание ** бит на канал)
  • точки к данные с соответствующим указателем размера и цикл через один кадр за раз. (Монокадр имеет один образец, который может быть 8, 16, 24 и т. Д. Стереоканал имеет два образца, которые могут быть 8, 16 или 24 бит на выборку, например, LR LR LR LR LR LR будет 6 кадров)
+0

Количество каналов 2 и бит на канал 16 ... поэтому я попытался с int16_t также, но не повезло. –

0

Заголовок файла сгенерированного Apple файла обычно не составляет 44 байта. Некоторые выпущенные Apple заголовки имеют длину 4k байт. Вы должны проверить заголовок RIFF волны для дополнительных байтов «FFLR». Если вы не пропустите это дополнительное заполнение заполнителя, вы получите примерно одну треть секунды в тишине (или, возможно, даже плохие данные).

+0

Так что вы рекомендуете узнать, сколько байтов имеет заголовок? –

+0

Если есть заполнение FLLR, подпись и длина ASCII «FFLR» будут в файле в (или рядом) заголовке в соответствии с спецификацией формата файла RIFF (реальная спецификация Microsoft, а не более распространенный пример с 44 байт-волнами.) – hotpaw2