[英]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.