iOS Audio(音频)

简介: 1. 播放音效#pragma mark 基本使用- (void)baseUse{ //1. 创建URL地址 NSURL *url = [[NSBundle mainBundle] URLForResource:@"buyao.

1. 播放音效

#pragma mark 基本使用
- (void)baseUse
{
    //1. 创建URL地址
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"buyao.wav" withExtension:nil];
    
    //2. 系统音效文件 SystemSoundID = UInt32
    SystemSoundID soundID;
    
    //3. 创建音效文件
    AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
    
    //4. 播放音效文件
    //4.1 不带震动的播放
    //AudioServicesPlaySystemSound(soundID);
    
    //4.2 带振动的播放 --> 真机才有效果
    AudioServicesPlayAlertSound(soundID);
    
    //5. 如果不需要播放了, 需要释放音效所占用的内存
    AudioServicesDisposeSystemSoundID(soundID);
}

2. 简单封装

MTAudioTool.h

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface MTAudioTools : NSObject
/** 播放系统音效*/
+ (void)playSystemSoundWithURL:(NSURL *)url;
/** 播放震动音效*/
+ (void)playAlertSoundWithURL:(NSURL *)url;
/** 清空音效文件的内存*/
+ (void)clearMemory;
@end

MTAudioTool.m


#import "MTAudioTools.h"

/** 缓存字典*/
static NSMutableDictionary *_soundIDDict;

@implementation MTAudioTools

// 只要头文件参与了编译调用
//+ (void)load

/** 缓存字典初始化*/
+ (void)initialize
{
    _soundIDDict = [NSMutableDictionary dictionary];
}

+ (void)playSystemSoundWithURL:(NSURL *)url
{
    // 不带震动的播放
    AudioServicesPlaySystemSound([self loadSoundIDWithURL:url]);
}

/** 播放震动音效*/
+ (void)playAlertSoundWithURL:(NSURL *)url
{
    // 带震动的播放
    AudioServicesPlayAlertSound([self loadSoundIDWithURL:url]);

}

#pragma mark 播放音效的公用方法
+ (SystemSoundID)loadSoundIDWithURL:(NSURL *)url
{
    // 思路思路
    // soundID重复创建 --> soundID每次创建, 就会有对应的URL地址产生
    // 可以将创建后的soundID 及 对应的URL 进行缓存处理
    
    //1. 获取URL的字符串
    NSString *urlStr = url.absoluteString;
    
    //2. 从缓存字典中根据URL来取soundID 系统音效文件
    SystemSoundID soundID = [_soundIDDict[urlStr] intValue];
    
    //需要在刚进入的时候, 判断缓存字典是否有url对应的soundID
    
    //3. 判断soundID是否为0, 如果为0, 说明没有找到, 需要创建
    if (soundID == 0) {
        //3.1 创建音效文件
        AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
        
        //3.2 缓存字典的添加键值
        _soundIDDict[urlStr] = @(soundID);
    }
    
    return soundID;
}


/** 清空音效文件的内存*/
+ (void)clearMemory
{
    //1. 遍历字典
    [_soundIDDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        //2. 清空音效文件的内存
        SystemSoundID soundID = [obj intValue];
        AudioServicesDisposeSystemSoundID(soundID);
    }];
}

@end

ViewController.m

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "MTAudioTools.h"

/**
 1. 导入AVFoundation框架
 2. 创建音效文件
 3. 播放音效文件
 
 音效: 非常短的音乐, 一般来说30秒以内的声音, 都算作音效
 */

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

#pragma mark 点击播放音效
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1. 获取URL地址
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"buyao.wav" withExtension:nil];
    
    //2. 调用工具类播放音效
    //[MTAudioTools playSystemSoundWithURL:url];
    
    [MTAudioTools playAlertSoundWithURL:url];
    
}

#pragma mark 当前控制器收到内存警告时会调用的方法
- (void)didReceiveMemoryWarning
{
    // 局部音效需要在这里进行释放
    [MTAudioTools clearMemory];
    NSLog(@"%s",__func__);
}

@end

3. 音乐播放

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

/**
 1. 需要使用AVFoundatiaon框架
 2. 创建音乐播放器
 3. 根据需求, 进行播放/暂停/停止
 */

@interface ViewController ()
@property (nonatomic, strong) AVAudioPlayer *player;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建音乐播放器
    
    //1. 获取URL路径
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"我爱你你却爱着她.mp3" withExtension:nil];
    
    //2. 创建一个error对象
    NSError *error;
    
    //3. 创建音乐播放器
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    
    if (error) {
        NSLog(@"有错误产生");
    }
    
}

- (IBAction)playClick:(id)sender {
    //1. 准备播放 --> 将音频文件加载到内存中 --> 这句话可以不写 --> play会隐式调用prepareToPlay方法. 但是规范来说, 还是会写上
    [self.player prepareToPlay];
    
    //2. 开始播放
    [self.player play];
}

- (IBAction)pauseClick:(id)sender {

    // 暂停播放
    [self.player pause];
}

- (IBAction)stopClick:(id)sender {
    // 停止播放
    [self.player stop];
    
    // 归零操作 / 时间重置 currentTime--> 秒为单位
    self.player.currentTime = 0;
}
@end

4. 录音

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

/**
 1. 需要使用AVFoundatiaon框架
 2. 创建录音对象
 3. 根据需求, 进行录音/暂停/停止
 */

@interface ViewController ()

@property (nonatomic, strong) AVAudioRecorder *recorder;

@property (nonatomic, strong) CADisplayLink *displayLink;

@end

@implementation ViewController

/**
 
 //录音
 //    //settings  设置参数  录音相关参数  声道  速率  采样率
 //    NSMutableDictionary *setting = [NSMutableDictionary dictionary];
 //    // 音频格式
 //    setting[AVFormatIDKey] = @(kAudioFormatAppleIMA4);
 //    // 音频采样率
 //    setting[AVSampleRateKey] = @(600.0);
 //    // 音频通道数
 //    setting[AVNumberOfChannelsKey] = @(1);
 //    // 线性音频的位深度
 //    setting[AVLinearPCMBitDepthKey] = @(8);
 */

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建录音对象
    //1. 获取URL地址 --> 具体的文件名路径
    //--> 注意之前是获取资源地址, 这里是指要将录音存放到哪里
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"recorde.wav"];
    
    //2. 将path字符串转换成NSURL --> file://
    NSURL *url = [NSURL fileURLWithPath:path];
    
    //3. 配置设置字典
    // 如果传空, 默认就是高质量
    // 录音的参数值
    NSMutableDictionary *setting = [NSMutableDictionary dictionary];
    
    //4. 创建Error对象 __autoreleasing 可以不加, 加上之后是最标准写法
    __autoreleasing NSError *error;
    
    //5. 创建录音对象
    self.recorder = [[AVAudioRecorder alloc] initWithURL:url settings:setting error:&error];
    
//    if (error) {
//        NSLog(@"error");
//    }
    
    //6. 打开分贝的检测
    self.recorder.meteringEnabled = YES;
    
    //7. 如果要在真机运行, 还需要一个session类, 并且制定分类为录音
    AVAudioSession *session = [AVAudioSession new];
    [session setCategory:AVAudioSessionCategoryRecord error:nil];
}

- (IBAction)recordClick:(id)sender {
    //1. 准备录音
    [self.recorder prepareToRecord];
    
    //2. 开始录音  --> 如果同一路径再次录音, 则会覆盖之前的文件
    [self.recorder record];
    
    //3. 进行分贝的循环检测 --> 添加计时器
    [self updateMetering];
}

- (IBAction)pauseClick:(id)sender {
    // 暂停录音  --> 如果用户只是暂停了, 应该提示用户进行保存操作
    [self.recorder pause];
    
    // 暂停循环
    self.displayLink.paused = YES;
}

- (IBAction)stopClick:(id)sender {
    // 停止录音 --> 之后停止录音时, 最终的录音文件才会生产
    [self.recorder stop];
    
    // 暂停循环
    self.displayLink.paused = YES;
    
    NSLog(@"停止录音");
}

#pragma mark 添加计时器
- (void)updateMetering
{
    // 如果没有displayLink就创建
    if (self.displayLink == nil) {
        //1. 创建displayLink
        self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateMeter)];
        
        //2. 添加到运行循环中
        [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    }
    
    // 判断如果暂停了循环, 就打开
    if (self.displayLink.isPaused) {
        self.displayLink.paused = NO;
    }
}

#pragma mark 循环调用的方法
- (void)updateMeter
{
    //需求: 自动停止录音 --> 根据分贝的大小来判断
    
    //1. 我们需要获取分贝信息
    //2. 设置分贝如果小于某个值, 一定时间后, 自动停止
    
    //1. 更新分贝信息
    [self.recorder updateMeters];
    
    //2. 获取分贝信息 --> iOS直接传0
    // 0 ~ -160 , 值最大是0, 最小是-160. 系统返回的是负值
    CGFloat power = [self.recorder averagePowerForChannel:0];
    
    //3. 实现2S自动停止
    static NSInteger number;
    
    //displayLink,一秒默认是60次, 如果120此的调用都小于某个分贝值, 我们就可以认为要自动停止
    
    //3.1 先判断用户是否小于某个分贝值 --> 用户是否没说话
    if (power < -30) {
        
        //3.2 如果发现很安静, 我们就可以记录一下, number进行叠加
        number++;
        
        //3.3 如果发现120次了, 都小于设定的分贝值
        if (number / 60 >= 2) {
            
            //3.4 调用停止方法
            [self stopClick:nil];
        }
    } else {
        number = 0;
    }
    
    NSLog(@"power: %f",power);
}

@end
目录
相关文章
|
iOS开发 设计模式 API
iOS Audio unit(音频单元)详解 关于音频单元托管
iOS Audio unit(音频单元)详解 关于音频单元托管 iOS  提供的音频处理插件支持混合,均衡,格式转换以及录制,回放,离线呈现和实时对话(如VoIP(互联网语音协议))的实时输入/输出。
2112 0
|
11天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
2月前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
118 1
|
2天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
4天前
|
存储 前端开发 Swift
探索iOS开发:从新手到专家的旅程
本文将带您领略iOS开发的奇妙之旅,从基础概念的理解到高级技巧的掌握,逐步深入iOS的世界。文章不仅分享技术知识,还鼓励读者在编程之路上保持好奇心和创新精神,实现个人成长与技术突破。
|
18天前
|
安全 数据处理 Swift
深入探索iOS开发中的Swift语言特性
本文旨在为开发者提供对Swift语言在iOS平台开发的深度理解,涵盖从基础语法到高级特性的全面分析。通过具体案例和代码示例,揭示Swift如何简化编程过程、提高代码效率,并促进iOS应用的创新。文章不仅适合初学者作为入门指南,也适合有经验的开发者深化对Swift语言的认识。
38 9
|
14天前
|
设计模式 Swift iOS开发
探索iOS开发:从基础到高级,打造你的第一款App
【10月更文挑战第40天】在这个数字时代,掌握移动应用开发已成为许多技术爱好者的梦想。本文将带你走进iOS开发的世界,从最基础的概念出发,逐步深入到高级功能实现,最终指导你完成自己的第一款App。无论你是编程新手还是有志于扩展技能的开发者,这篇文章都将为你提供一条清晰的学习路径。让我们一起开始这段旅程吧!
|
18天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。