簡體   English   中英

從波形錄制的音頻文件中刪除初始靜音

[英]Remove initial silence from recorded audio file of wave type

誰能幫助我消除錄制的音頻文件中的初始靜音?

我正在獲取wav文件的數據字節,並忽略了前44個頭字節字節,獲得0字節的結束范圍(在wave文件中處於靜默狀態)。

從總數據字節,靜音音頻字節的結束范圍和文件的總持續時間之后,我正在計算音頻文件的靜音時間,並從音頻文件中修剪那么多時間。

但是問題仍然在於音頻文件中還剩下一些無聲部分。

所以不確定我是否錯過了什么?

- (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){
         }
     }];
}

我在這里做錯了什么?

您的文件可能沒有完全靜音嗎? 也許您的樣本的值為1或2或3,從技術上講它不是靜默的,但非常安靜。

Wave文件如果是16位,則存儲為帶符號的數字;如果是8位,則存儲為無符號的。 您正在處理數據並將其轉換為無符號字節:uint8_t * bytePtr =(uint8_t *)[Wave1 bytes];

您需要知道可以從標題獲得的wave文件的格式。 (它可能會使用8位,16位,24位等樣本大小)

如果是16位單聲道,則需要使用:

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

您的循環一次計數一個字節,因此您需要對其進行調整以增加幀大小的大小。

您也不考慮單聲道/立體聲。
通常,您的processAudio函數需要更多詳細信息,並應考慮每幀的通道數(立體聲/單聲道)和樣本大小的大小。

這是iOS類型的wave標頭。 您可以轉換前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;

所以你的待辦事項清單是

  • 從標題中提取字段
  • 具體獲得通道數和每個通道的位數(請注意**每個通道的BITS)
  • 使用適當的大小指針指向數據,並一次遍歷一幀。 (單幀具有一個可能為8、16、24等位的樣本。立體聲幀具有兩個可能為每個樣本8、16或24位的采樣。例如LR LR LR LR LR LR將為6幀)

Apple生成的wave文件的標頭通常不是44個字節。 Apple生成的某些標頭的長度為4k字節。 您必須檢查wave RIFF標頭中是否有額外的“ FFLR”字節。 如果您不跳過這些多余的填充,您將在安靜狀態下停留大約十分之一秒的時間(甚至可能是不良數據)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM