[英]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;
所以你的待辦事項清單是
Apple生成的wave文件的標頭通常不是44個字節。 Apple生成的某些標頭的長度為4k字節。 您必須檢查wave RIFF標頭中是否有額外的“ FFLR”字節。 如果您不跳過這些多余的填充,您將在安靜狀態下停留大約十分之一秒的時間(甚至可能是不良數據)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.