項(xiàng)目開發(fā)需求
- 應(yīng)用場(chǎng)景:項(xiàng)目中用到了答疑提問的功能亲桥,這個(gè)功能的應(yīng)用就是學(xué)員端提交答案和教師端回答問題,兩端配合使用固耘,那么考慮到學(xué)員提問的時(shí)候?qū)栴}描述不清晰以及在教師回答問題的時(shí)候更加方便快速题篷,所以就加上了錄音答疑的功能。
音頻相關(guān)知識(shí)介紹:
文件格式(不同的文件格式厅目,可保存不同的編碼格式的文件)
1.1 WAV:
特點(diǎn):音質(zhì)最好的格式番枚,對(duì)應(yīng)PCM編碼
適用:多媒體開發(fā),保存音樂和音效素材损敷。
1.2 MP3:
特點(diǎn):音質(zhì)好葫笼,壓縮比比較高,被大量軟件和硬件支持拗馒。
適用:適合用于比較高要求的音樂欣賞路星。
1.3 caf:
特點(diǎn):適用于幾乎iOS中所有的編碼格式。編碼格式
2.1 PCM
PCM:脈沖編碼調(diào)制诱桂,是一種非壓縮音頻數(shù)字化技術(shù)洋丐,是一種未壓縮的原音重現(xiàn),數(shù)字模式下访诱,音頻的初始化信號(hào)是PCM.
2.2 MP3
2.3 AAC
AAC:其實(shí)是“高級(jí)音頻編碼(advanced audio coding)”的縮寫垫挨,他是被設(shè)計(jì)用來(lái)取代MPC格式的。
2.4 HE-AAC
HE-AAC是AAC的一個(gè)超集触菜,這個(gè)“High efficiency”九榔,HE-AAC是專門為低比特率所優(yōu)化的一種音頻編碼格式。
2.5 AMR
AMR全稱是“Adaptive Multi-Rate”涡相,它也是另一個(gè)專門為“說話(speech)”所優(yōu)化的編碼格式哲泊,也是適合低比特率環(huán)境下采用。
2.6 ALAC
它全稱是“Apple Lossless”催蝗,這是一種沒有任何質(zhì)量損失的音頻編碼方式切威,也就是我們說的無(wú)損壓縮。
2.7 IMA4
IMA4:這是一個(gè)在16-bit音頻文件下按照4:1的壓縮比來(lái)進(jìn)行壓縮的格式丙号。
考慮到服務(wù)端要保證iOS端和安卓端的同樣的效果先朦,因此在iOS端錄音所生成的Caf格式錄音文件轉(zhuǎn)碼為Mp3后進(jìn)行上傳,這樣就保證兩端音頻播放的一致性犬缨。
功能實(shí)現(xiàn)核心代碼
因?yàn)槲視?huì)在文章的最后面附上完整的demo喳魏,因此這里只展示核心代碼部分,以及注意事項(xiàng)怀薛。
- 創(chuàng)建錄音并設(shè)置參數(shù)
#pragma mark - 創(chuàng)建錄音
-(void)createRecorder{
// Setup audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
if ([session respondsToSelector:@selector(requestRecordPermission:)]) {
[session requestRecordPermission:^(BOOL available) {
if (available) {
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:@"無(wú)法錄音" message:@"請(qǐng)?jiān)凇霸O(shè)置-隱私-麥克風(fēng)”選項(xiàng)中允許xx訪問你的麥克風(fēng)" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil] show];
return ;
});
}
}];
}
//錄音參數(shù)設(shè)置設(shè)置
NSMutableDictionary *settingDic = [[NSMutableDictionary alloc] init];
//設(shè)置錄音格式
[settingDic setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
//設(shè)置錄音采樣率(Hz) 如:AVSampleRateKey==8000/44100/96000(影響音頻的質(zhì)量)//11025.0
[settingDic setValue:[NSNumber numberWithFloat:11025.0] forKey:AVSampleRateKey];
//錄音通道數(shù) 1 或 2
[settingDic setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
//線性采樣位數(shù) 8刺彩、16、24、32
[settingDic setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
//錄音的質(zhì)量
// [settingDic setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
[settingDic setValue:[NSNumber numberWithInt:AVAudioQualityHigh] forKey:AVEncoderAudioQualityKey];
//錄音文件最終地址
_recordURL=[CDPAudioRecorder getAudioRecordFilePath];
NSError *error=nil;
//初始化AVAudioRecorder
_recorder = [[AVAudioRecorder alloc] initWithURL:_recordURL settings:settingDic error:&error];
//開啟音量分貝數(shù)監(jiān)測(cè)
_recorder.meteringEnabled = YES;
_recorder.delegate=self;
if (_recorder&&[_recorder prepareToRecord]) {
}
else{
DLog(@"CDPAudioRecorder錄音初始化失敗error:%@",error);
}
}
- 錄音后會(huì)生成Caf格式的文件创倔,然后把文件轉(zhuǎn)化為Mp3格式嗡害,
現(xiàn)在最主流的就是用lame框架來(lái)實(shí)現(xiàn)啦
不過lame只支持32位的,這對(duì)64位的很坑
不過我們可以下載lame的源碼然后自己轉(zhuǎn)成64位的就可以用啦
下面就是步驟畦攘,跟著動(dòng)起來(lái)吧霸妹!
一、下載lame的最新版念搬。地址https://sourceforge.net/projects/lame/files/lame/
這個(gè)就行啦
二抑堡、還需要下載一個(gè)腳本,地址https://github.com/kewlbear/lame-ios-build
三朗徊、這兩個(gè)就是我下載的兩個(gè)文件夾首妖,在桌面上
四、打開lame-ios-build-master 文件爷恳,把里面的build-lame.sh 放到lame-3.99.5 文件夾中
五有缆、最重要的來(lái)啦。打開build-lame.sh文件温亲,找到如圖所示的地方棚壁,注釋很清楚啦,保存關(guān)閉
六栈虚、打開終端袖外,cd到lame-3.99.5這個(gè)目錄下,就是下載lame源碼的目錄
輸入
chmod 777 build-lame.sh
再輸入
./build-lame.sh
然后等待編譯魂务,差不多不用1分鐘就編譯完了
七曼验、打開lame-3.99.5目錄,在里面會(huì)看到兩個(gè)文件夾
thin-lame目錄下有幾個(gè)文件夾粘姜,里面放的是不同指令下的我們要用到的.h和.a文件
fat-lame目錄下則是不同指令下合并編譯出來(lái)的.h和.a文件鬓照,也就是我們最終會(huì)用到的
拿到我們想要的就可以去轉(zhuǎn)MP3啦
錄音轉(zhuǎn)換為mp3格式:
- (void)audio_PCMtoMP3 {
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [path stringByAppendingPathComponent:@"CDPAudioFiles/CDPAudioRecord.caf"];
NSString *audioPath = [LameTool audioToMP3:filePath isDeleteSourchFile:NO];
if ([audioPath isEqualToString:@"fail"]) {
NSLog(@"上傳失敗");
} else {
self.audioString = audioPath;
[_recorder setRecordURL:[NSURL URLWithString:audioPath]];
}
NSLog(@"轉(zhuǎn)碼amr格式成功----文件地址為:%@",filePath);
}
+ (NSString *)audioToMP3: (NSString *)sourcePath isDeleteSourchFile:(BOOL)isDelete {
// 輸入路徑
NSString *inPath = sourcePath;
// 判斷輸入路徑是否存在
NSFileManager *fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:sourcePath]) {
NSLog(@"文件不存在");
return @"fail";
}
// 輸出路徑
NSString *outPath = [[sourcePath stringByDeletingPathExtension] stringByAppendingString:@".mp3"];
@try {
int read, write;
FILE *pcm = fopen([inPath cStringUsingEncoding:1], "rb"); //source 被轉(zhuǎn)換的音頻文件位置
if(pcm == NULL) {
NSLog(@"file not found");
return @"fail";
}
fseek(pcm, 4*1024, SEEK_CUR); //skip file header
FILE *mp3 = fopen([outPath cStringUsingEncoding:1], "wb"); //output 輸出生成的Mp3文件位置
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE*2];
unsigned char mp3_buffer[MP3_SIZE];
// lame_t lame = lame_init();
// lame_set_in_samplerate(lame, 8000);//8000/11025.0//44100
// lame_set_VBR(lame, vbr_default);
// lame_init_params(lame);
lame_t lame = lame_init();
lame_set_num_channels(lame, 2);//設(shè)置1為單通道,默認(rèn)為2雙通道
lame_set_in_samplerate(lame, 11025.0);//11025.0
//lame_set_VBR(lame, vbr_default);
lame_set_brate(lame, 16);
lame_set_mode(lame, 3);
lame_set_quality(lame, 2);
lame_init_params(lame);
do {
//size_t size = (size_t)(2 * sizeof(short int));
//read = fread(pcm_buffer, size, PCM_SIZE, pcm);
read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
if (read == 0)
write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
else
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
fwrite(mp3_buffer, write, 1, mp3);
} while (read != 0);
lame_close(lame);
fclose(mp3);
fclose(pcm);
}
@catch (NSException *exception) {
NSLog(@"%@",[exception description]);
}
@finally {
NSLog(@"MP3生成成功:");
if (isDelete) {
NSError *error;
[fm removeItemAtPath:sourcePath error:&error];
if (error == nil) {
NSLog(@"刪除源文件成功");
}
}
return outPath;
}
}
注意事項(xiàng):這里的幾個(gè)參數(shù)配置:創(chuàng)建錄音的時(shí)候頻率為多少孤紧,轉(zhuǎn)化為mp3的時(shí)候就使用多少:
錄音:
//設(shè)置錄音采樣率(Hz) 如:AVSampleRateKey==8000/44100/96000(影響音頻的質(zhì)量)//11025.0
[settingDic setValue:[NSNumber numberWithFloat:11025.0] forKey:AVSampleRateKey];
//錄音通道數(shù) 1 或 2
轉(zhuǎn)化:
lame_t lame = lame_init();
lame_set_num_channels(lame, 2);//設(shè)置1為單通道豺裆,默認(rèn)為2雙通道
lame_set_in_samplerate(lame, 11025.0);//11025.0
//lame_set_VBR(lame, vbr_default);
lame_set_brate(lame, 16);
lame_set_mode(lame, 3);
lame_set_quality(lame, 2);
lame_init_params(lame);
到此就結(jié)束了,簡(jiǎn)單的demo如下: