音頻重采樣步驟
- 創(chuàng)建采樣上下文
- 設(shè)置輸入緩沖區(qū)
- 設(shè)置輸出緩沖區(qū)
- 打開文件開始重采樣
- 檢查輸出緩沖區(qū)是否還有殘余的樣本
- 釋放資源
+ (void)resample:(ResampleAudioSpec*)input outPut:(ResampleAudioSpec*)output {
NSFileHandle *inputFile = [NSFileHandle fileHandleForReadingAtPath:[NSString stringWithCString:input->filename encoding:NSUTF8StringEncoding]];
NSError *error;
NSString *outfileName = [NSString stringWithCString:output->filename encoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager]createFileAtPath:outfileName contents:nil attributes:nil];
NSFileHandle *outFile = [NSFileHandle fileHandleForWritingToURL:[NSURL fileURLWithPath:outfileName] error:&error];
if (error) {
NSLog(@"outfile文件創(chuàng)建失敼胛骸:%@", error.description);
[inputFile closeFile];
return;
}
// 輸入緩沖區(qū)
// 指向緩沖區(qū)的指針
uint8_t **inData = nullptr;
NSData *infile;
// 緩沖區(qū)的大小
int inLineSize = 0;
// 聲道數(shù)
int inChs = av_get_channel_layout_nb_channels(input->chLayout);
// 一個樣本的大小
int inBytesPerSample = av_get_bytes_per_sample(input->sampleFmt) * inChs;
// 緩沖區(qū)的樣本數(shù)量
int inSamples = 1024;
// 讀取文件數(shù)據(jù)的大小
int len = 0;
// 輸出緩沖區(qū)
// 指向緩沖區(qū)的指針
uint8_t **outData = nullptr;
// 緩沖區(qū)的大小
int outLineSize = 0;
// 聲道數(shù)
int outChs = av_get_channel_layout_nb_channels(output->chLayout);
// 一個樣本的大小
int outBytesPerSample = av_get_bytes_per_sample(output->sampleFmt) * outChs;
// 緩沖區(qū)的樣本數(shù)量
int outSamples = av_rescale_rnd((int64_t)output->sampleRate,
(int64_t)inSamples,
(int64_t)input->sampleRate,
AV_ROUND_UP);
/*
inSampleRate inSamples
------------- = -----------
outSampleRate outSamples
outSamples = outSampleRate * inSamples / inSampleRate
*/
NSLog(@"輸入緩沖區(qū) inSampleRate: %d - inSamples: %d", input->sampleRate, inSamples);
NSLog(@"輸出緩沖區(qū) inSampleRate: %d - outSamples: %d", output->sampleRate, outSamples);
int ret = 0;
// 創(chuàng)建重采樣上下文
/**
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
int log_offset, void *log_ctx);
*/
SwrContext *ctx = swr_alloc_set_opts(nullptr,
output->chLayout,
output->sampleFmt,
output->sampleRate,
input->chLayout,
input->sampleFmt,
input->sampleRate,
0,
nullptr);
if (!ctx) {
NSLog(@"swr_alloc_set_opts error");
goto end;
}
// 初始化重采樣上下文
ret = swr_init(ctx);
if (ret < 0) {
ERROR_BUF(ret);
NSLog(@"swr_init error: %s", errbuf);
goto end;
}
//創(chuàng)建輸入緩沖區(qū)
ret = av_samples_alloc_array_and_samples(&inData,
&inLineSize,
inChs,
inSamples,
input->sampleFmt,
1);
if (ret < 0) {
ERROR_BUF(ret);
NSLog(@"av_samples_alloc_array_and_samples error: %s", errbuf);
goto end;
}
//創(chuàng)建輸出緩沖區(qū)
ret = av_samples_alloc_array_and_samples(&outData,
&outLineSize,
outChs,
outSamples,
output->sampleFmt,
1);
if (ret < 0) {
ERROR_BUF(ret);
NSLog(@"av_samples_alloc_array_and_samples error: %s", errbuf);
goto end;
}
// 讀取文件數(shù)據(jù)
[inputFile seekToFileOffset:0];
infile = [inputFile readDataOfLength:inLineSize];
inData[0] = (uint8_t*) [infile bytes];
len = (int)[infile length];
while (len > 0) {
// 讀取樣本數(shù)量
inSamples = len / inBytesPerSample;
ret = swr_convert(ctx,
outData,
outSamples,
(const uint8_t **)inData,
inSamples);
if (ret < 0) {
ERROR_BUF(ret);
NSLog(@"swr_convert error: %s", errbuf);
goto end;
}
// 將裝換后的數(shù)據(jù)寫入輸出文件中
[outFile writeData:[NSData dataWithBytes:outData[0] length:ret *outBytesPerSample]];
[outFile seekToEndOfFile];
// 繼續(xù)讀下一段輸入數(shù)據(jù)
infile = [inputFile readDataOfLength:inLineSize];
inData[0] = (uint8_t*) [infile bytes];
len = (int)[infile length];
NSLog(@"---------len: %d -- inLineSize: %d --- ret: %d", len, inLineSize, ret);
}
// 檢查一下輸出緩沖區(qū)是否還有殘留的樣本(已經(jīng)重采樣過的,換換過的)
while ((ret = swr_convert(ctx, outData, outSamples, nullptr, 0)) > 0) {
[outFile writeData:[NSData dataWithBytes:(char *)outData[0] length:ret * outBytesPerSample]];
}
NSLog(@"-----end----");
end:
[inputFile closeFile];
[outFile closeFile];
if (inData) {
av_freep(&inData[0]);
}
av_freep(&inData);
if (outData) {
av_freep(&outData[0]);
}
av_freep(&outData);
swr_free(&ctx);
}