ios android mid音频文件,iOS 录音 音频 视频 控制中心
錄音
最近項目中需要錄音功能,為此在寫了一個錄音的小模塊。
首先需要添加AVFoundation.framework
lame.h 幫助鏈接
下面直接上代碼
#import
#import
#import
typedef void(^AudioModelBlock)(NSInteger duration);
@protocol AudioModelDelegate
- (void)recordResult:(NSString *)path error:(NSError *)error;
@end
@interface AudioModel : NSObject {
AVAudioRecorder *_audioRecorder;
AVAudioPlayer *_audioPlayer;
NSTimer *_timer;
NSString *_name;
}
@property (nonatomic, assign) NSInteger duration;
@property (nonatomic, copy) AudioModelBlock block;
@property (nonatomic, assign) id delegate;
#pragma mark - record
//開始錄音 或 恢復(fù)錄音
- (void)record;
//暫停錄音
- (void)pauseRecotd;
//停止錄音
- (void)stopRecord;
#pragma mark - play
//播放錄音
- (void)playRecord:(NSString *)path;
#pragma mark - file
//移除錄音
- (void)removeFile;
#import "AudioModel.h"
#import "lame.h"
@implementation AudioModel
- (instancetype)init {
self = [super init];
if (self) {
}
return self;
}
#pragma mark - setting
//獲取錄音文件設(shè)置
- (NSDictionary *)getAudioSetting {
NSMutableDictionary *dicM = [NSMutableDictionary dictionary];
//設(shè)置錄音格式
[dicM setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
//設(shè)置錄音采樣率
[dicM setObject:@(20000) forKey:AVSampleRateKey];
//設(shè)置通道,這里采用單聲通道
[dicM setObject:@(2) forKey:AVNumberOfChannelsKey];
// //每個采樣點位數(shù),8,16,24,32
// [dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
// [dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
//音頻編碼質(zhì)量
[dicM setObject:@(AVAudioQualityMedium) forKey:AVEncoderAudioQualityKey];
//其他
return dicM;
}
#pragma mark - path
- (NSString *)getBasePath {
NSString *urlStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
urlStr = [urlStr stringByAppendingPathComponent:[YLSaveObjectToLocal loadObjectForKey:@"userMid"]];
urlStr = [urlStr stringByAppendingPathComponent:[YLCoreTool getNowWithFormatter:@"yyyyMMdd"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:urlStr]) {
}
else {
[fileManager createDirectoryAtPath:urlStr withIntermediateDirectories:YES attributes:nil error:nil];
}
return urlStr;
}
//獲取錄音文件保存路徑
- (NSString *)getSavePath {
NSString *urlStr = [self getBasePath];
urlStr = [urlStr stringByAppendingPathComponent:_name];
urlStr = [urlStr stringByAppendingString:@".caf"];
return urlStr;
}
- (NSString *)getMp3FilePath {
NSString *urlStr = [self getBasePath];
urlStr = [urlStr stringByAppendingPathComponent:_name];
urlStr = [urlStr stringByAppendingString:@".mp3"];
return urlStr;
}
- (void)removeFile {
NSString *urlStr = [self getBasePath];
urlStr = [urlStr stringByAppendingPathComponent:_name];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *arr = @[@".caf",@".mp3"];
for (NSString *type in arr) {
NSString *path = [urlStr stringByAppendingString:type];
if ([fileManager fileExistsAtPath:path]) {
[fileManager removeItemAtPath:path error:nil];
}
}
}
#pragma mark - action
//開始錄音 或 恢復(fù)錄音
- (void)record {
_name = [YLCoreTool getNowWithFormatter:@"yyyyMMdd_HHmmss"];
//創(chuàng)建錄音文件保存路徑
NSURL *url = [NSURL URLWithString: [self getSavePath]];
//創(chuàng)建錄音格式設(shè)置
NSDictionary *setting = [self getAudioSetting];
//設(shè)置音頻會話 不然不錄制
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
//設(shè)置為播放和錄音狀態(tài),以便可以在錄制完之后播放錄音
[audioSession setCategory:AVAudioSessionCategoryRecord error:nil];
[audioSession setActive:YES error:nil];
//創(chuàng)建錄音機
NSError *error = nil;
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:setting error:&error];
_audioRecorder.delegate = self;
if (error) {
NSLog(@"creat audioRecorder error:%@", error.localizedDescription);
} else {
if (![_audioRecorder isRecording]) {
if ([_audioRecorder prepareToRecord]) {
if ([_audioRecorder record]) {
self.timer.fireDate = [NSDate distantPast];
}
}
}
}
}
//暫停錄音
- (void)pauseRecotd {
if ([_audioRecorder isRecording]) {
[_audioRecorder pause];
self.timer.fireDate = [NSDate distantFuture];
}
}
//停止錄音
- (void)stopRecord {
[_audioRecorder stop];
self.timer.fireDate = [NSDate distantFuture];
}
//計時器計時
- (void)handleTimerAction {
self.duration = _audioRecorder.currentTime;
}
//播放錄音
- (void)playRecord:(NSString *)path {
//播放聲音小時可以設(shè)置
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory :AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
NSURL *url = [NSURL URLWithString: path];
NSError *error = nil;
_audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
_audioPlayer.numberOfLoops = 0;
_audioPlayer.delegate = self;
[_audioPlayer prepareToPlay];
if (error) {
NSLog(@"creat audioPlayer error: %@", error.localizedDescription);
}
else {
[_audioPlayer play];
}
}
- (void)playAVItem {
}
#pragma mark - AVAudioRecorderDelegate
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error {
if (error) {
NSLog(@"%@",error.localizedDescription);
}
}
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
NSLog(@"錄制完成");
[self convertToMp3];
_audioRecorder = nil;
}
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
_audioPlayer = nil;
}
#pragma mark - tool
- (void)convertToMp3
{
NSString *filePath = [self getMp3FilePath];
@try {
int read,write;
//只讀方式打開被轉(zhuǎn)換音頻文件
FILE *pcm = fopen([[self getSavePath] cStringUsingEncoding:1], "rb");
fseek(pcm, 4 * 1024, SEEK_CUR);//刪除頭,否則在前一秒鐘會有雜音
//只寫方式打開生成的MP3文件
FILE *mp3 = fopen([filePath cStringUsingEncoding:1], "wb");
const int PCM_SIZE = 8192;
const int MP3_SIZE = 8192;
short int pcm_buffer[PCM_SIZE * 2];
unsigned char mp3_buffer[MP3_SIZE];
//這里要注意,lame的配置要跟AVAudioRecorder的配置一致,否則會造成轉(zhuǎn)換不成功
lame_t lame = lame_init();
lame_set_VBR(lame, vbr_default);
lame_set_num_channels(lame,2);//默認為2雙通道
lame_set_in_samplerate(lame, 20000);//11025.0
lame_set_brate(lame,8);
lame_set_mode(lame,3);
lame_set_quality(lame,5); /* 2=high 5 = medium 7=low 音質(zhì)*/
lame_init_params(lame);
do {
//以二進制形式讀取文件中的數(shù)據(jù)
read = (int)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);
//二進制形式寫數(shù)據(jù)到文件中 mp3_buffer:數(shù)據(jù)輸出到文件的緩沖區(qū)首地址 write:一個數(shù)據(jù)塊的字節(jié)數(shù) 1:指定一次輸出數(shù)據(jù)塊的個數(shù) mp3:文件指針
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 ([self.delegate respondsToSelector:@selector(recordResult:error:)]) {
[self.delegate recordResult:[self getMp3FilePath] error:nil];
}
}
}
#pragma mark - set and get
- (void)setDuration:(NSInteger)duration {
_duration = duration;
if (self.block) {
self.block(_duration);
}
}
-(NSTimer *)timer{
if (!_timer) {
_timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(handleTimerAction) userInfo:nil repeats:YES];
}
return _timer;
}
/**
* 錄音聲波狀態(tài)設(shè)置
*/
// _audioRecorder.meteringEnabled = YES;//如果需要監(jiān)控聲波則必須設(shè)置為YES
//-(void)audioPowerChange{
// [self.audioRecorder updateMeters];//更新測量值
// float power= [self.audioRecorder averagePowerForChannel:0];//取得第一個通道的音頻,注意音頻強度范圍時-160到0
// CGFloat progress=(1.0/160.0)*(power+160.0);
// [self.audioPower setProgress:progress];
//}
// 獲取音頻時長
//AVURLAsset* audioAsset =[AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:self.savePath] options:nil];
//CMTime audioDuration = audioAsset.duration;
//float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
音頻和視頻
音頻和視頻播放使用的ZFPlayer,有興趣的話可以自己研究下
控制中心 后臺播放
需要打開相應(yīng)的Background Models
屏幕快照 2018-08-20 下午5.23.51.png
AppDelegate 中
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//處理中斷事件的通知 播放
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
//開啟后臺處理多媒體事件
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
return YES;
}
//處理中斷事件
-(void)handleInterreption:(NSNotification *)sender
{
ZFPlayerView *player = [ZFPlayerView sharedPlayerView];
if(player.state == ZFPlayerStatePause)
{
[player play];
}
else
{
[player pause];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
//ZFPlayerView會監(jiān)聽UIApplicationWillResignActiveNotification,自動關(guān)閉后臺播放
//這里是重新打開
[self handleInterreption:nil];
}
//控制中心操作
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
if (event.type == UIEventTypeRemoteControl) {
NSInteger order = -1;
switch (event.subtype) {
case UIEventSubtypeRemoteControlPause:
order = UIEventSubtypeRemoteControlPause;
break;
case UIEventSubtypeRemoteControlPlay:
order = UIEventSubtypeRemoteControlPlay;
break;
case UIEventSubtypeRemoteControlNextTrack:
order = UIEventSubtypeRemoteControlNextTrack;
break;
case UIEventSubtypeRemoteControlPreviousTrack:
order = UIEventSubtypeRemoteControlPreviousTrack;
break;
case UIEventSubtypeRemoteControlTogglePlayPause:
order = UIEventSubtypeRemoteControlTogglePlayPause;
break;
default:
order = -1;
break;
}
NSDictionary *dict = @{@"order":@(order)};
[[NSNotificationCenter defaultCenter] postNotificationName:@"kAppDidReceiveRemoteControlNotification" object:nil userInfo:dict];
}
}
控制文件中,如ViewController等
這里需要添加MediaPlayer.framework
#import
//監(jiān)聽控制中心事件
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listeningRemoteControl:) name:@"kAppDidReceiveRemoteControlNotification" object:nil];
}
//model 為自己定義
//播放時調(diào)用此函數(shù)更新控制中心
- (void)setNowPlayingInfo:(Model *)model {
NSMutableDictionary *songDict = [NSMutableDictionary dictionary];
//歌名
[songDict setObject:model.title forKey:MPMediaItemPropertyTitle];
//歌手名
[songDict setObject:AppName forKey:MPMediaItemPropertyArtist];
//總時長
[songDict setObject:[NSNumber numberWithInt:[model.time intValue] * 60] forKey:MPMediaItemPropertyPlaybackDuration];
//圖片
MPMediaItemArtwork *imageItem = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"%@Logo", PREFIX_NAME]]];
[songDict setObject:imageItem forKey:MPMediaItemPropertyArtwork];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songDict];
}
//控制中心事件操作
-(void)listeningRemoteControl:(NSNotification *)sender
{
NSDictionary *dict=sender.userInfo;
NSInteger order = [[dict objectForKey:@"order"] integerValue];
switch (order) {
//暫停
case UIEventSubtypeRemoteControlPause:
[self.playerView pause];
break;
//播放
case UIEventSubtypeRemoteControlPlay:
[self.playerView play];
break;
//暫停播放切換
case UIEventSubtypeRemoteControlTogglePlayPause:
{
if(self.playerView.state == ZFPlayerStatePause)
{
[self.playerView play];
}
else
{
[self.playerView pause];
}
break;
}
//下一首
case UIEventSubtypeRemoteControlNextTrack:
{
NSInteger index = [self.models indexOfObject:self.currentModel];
index = index + 1;
if (index < self.models.count) {
//這里是用于等待界面渲染
[NSTimer scheduledTimerWithTimeInterval:0.02 repeats:NO block:^(NSTimer * timer) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:index];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}];
}
break;
}
//上一首
case UIEventSubtypeRemoteControlPreviousTrack:
{
NSInteger index = [self.models indexOfObject:self.currentModel];
index = index - 1;
if (index >= 0) {
if (index < self.models.count) {
[NSTimer scheduledTimerWithTimeInterval:0.02 repeats:NO block:^(NSTimer * timer) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:index];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}];
}
}
break;
}
default:
break;
}
}
總結(jié)
以上是生活随笔為你收集整理的ios android mid音频文件,iOS 录音 音频 视频 控制中心的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机录音机应用程序在哪,录音机有什么作
- 下一篇: AT89S52最小系统