1、MediaRecorder錄音,MediaPlayer播放,使用的時(shí)候注意他們的生命周期。
林口ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書合作)期待與您的合作!
2、模擬器上播放聲音是沒問題的,pc外放能聽的到
還有問題可以追問
網(wǎng)上有很多博客說添加IOS10之后新增的Notification Service Extension才可以推送Apns自定義鈴聲,實(shí)際上是不對(duì)的,簡(jiǎn)單的自定義語音推送IOS10之前就已經(jīng)支持,而且APNS Server與deviceToken直接相關(guān)聯(lián),自然也不存在許多博客說的殺死App后接受不到推送的問題。
有關(guān)Notification Service Extension多媒體拓展問題可參考
本文提供簡(jiǎn)單的自定義語音推送解決方案。
修改蘋果原生推送聲音:
(1)App在后臺(tái)或者被殺死時(shí),服務(wù)器給你推送的userinfo中sound字段的value和你本地的聲音文件名一致時(shí),這樣就可以播放你本地自定義的語音文件(mp3,wav等常見語音格式都可以支持)。
(2)App運(yùn)行在前臺(tái)時(shí)大部分App會(huì)關(guān)閉掉UNNotificationPresentationOptionSound權(quán)限,當(dāng)你有類似美團(tuán)接單,支付寶到賬等需前臺(tái)響鈴的需求時(shí)需要自己寫響鈴方法,這里主要有兩種解決方案。
方案1播放系統(tǒng)音效
將此方法在應(yīng)用在前臺(tái)處理推送的方法中調(diào)用,注意區(qū)分iOS10前后處理方法的不同。
方案2:AVAudioPlayer播放
單例一個(gè)AVAudioPlayer控制類
這里我們推薦使用第一種方法,通過系統(tǒng)方法進(jìn)行播放。
Core Audio 是iOS和MAC系統(tǒng)中的關(guān)于數(shù)字音頻處理的基礎(chǔ),它是應(yīng)用程序用來處理音頻的一組軟件框架,所有關(guān)于iOS音頻開發(fā)的接口都是由Core Audio來提供或者經(jīng)過它提供的接口來進(jìn)行封裝的。
其實(shí)一句話,它是任何iOS或者M(jìn)AC系統(tǒng)音頻處理框架的基礎(chǔ)。
具體可以用官方文檔的一張圖表示。
接下來我們就一起分析一下。
這里的高級(jí)別服務(wù),更加接近于頂層,基本上我們很多關(guān)于音頻開發(fā)的工作在這一層就可以完成。
它位于框架 AudioToolbox 中。
提供錄制、播放、暫停、循環(huán)、和同步音頻它自動(dòng)采用必要的編解碼器處理壓縮的音頻格式。
要在iOS設(shè)備上播放和錄制音頻,蘋果推薦我們使用 AVFoundation 框架中的 AVAudioPlayer 和 AVAudioRecorder 類。雖然用法比較簡(jiǎn)單,但是不支持流式;這就意味著:在播放音頻前,必須等到整個(gè)音頻加載完成后,才能開始播放音頻;錄音時(shí),也必須等到錄音結(jié)束后,才能獲取到錄音數(shù)據(jù)。這給應(yīng)用造成了很大的局限性。為了解決這個(gè)問題,我們就需要使用 Audio Queue Services 來播放和錄制音頻。感興趣的可以看我前面寫的幾篇關(guān)于 Audio Queue Services 的文章。這里只是簡(jiǎn)單的給出錄音和播放的原理圖,具體原理和流程,看我前面寫的那幾篇,都有詳細(xì)的介紹。
它位于框架 AVFoundation 中。
是專為IOS平臺(tái)提供的基于Objective-C接口的音頻播放類,可以支持iOS所支持的所有音頻的播放,它主要支持以下音頻格式。
這個(gè)是純OC的實(shí)現(xiàn),特點(diǎn)就是調(diào)用簡(jiǎn)單,下面簡(jiǎn)單的看一下他的API。
由 Audio File 與 Audio Converter 組合而成,提供壓縮及無壓縮音頻文件的讀寫能力。
它與 Audio File Services 、 Audio File Stream Services 和 Audio Queue Services 等同時(shí)存在 AudioToolbox 框架中。 ExtendedAudioFile 相對(duì) Audio File Services 和 Audio Converter Services ,API調(diào)用非常簡(jiǎn)單和明確,并且不需要去處理 AudioStreamPacketDescription ,在實(shí)際開發(fā)中邏輯更為清晰。
它就是存在框架 OpenAL 中。
是CoreAudio對(duì)OpenAL標(biāo)準(zhǔn)的實(shí)現(xiàn),可以播放3D混音效果。
OpenAL 主要的功能是在來源物體、音效緩沖和收聽者中編碼。來源物體包含一個(gè)指向緩沖區(qū)的指標(biāo)、聲音的速度、位置和方向,以及聲音強(qiáng)度。收聽者物體包含收聽者的速度、位置和方向,以及全部聲音的整體增益。緩沖里包含 8 或 16 位元、單聲道或立體聲 PCM 格式的音效資料,表現(xiàn)引擎進(jìn)行所有必要的計(jì)算,如距離衰減、多普勒效應(yīng)等。
不同于 OpenGL 規(guī)格,OpenAL 規(guī)格包含兩個(gè)API分支;以實(shí)際 OpenAL 函式組成的核心,和 ALC API , ALC 用于管理表現(xiàn)內(nèi)容、資源使用情況,并將跨平臺(tái)風(fēng)格封在其中。還有 “ALUT ”程式庫,提供高階“易用”的函式,其定位相當(dāng)于 OpenGL 的 GLUT 。
該層功能比較齊全,包括音頻數(shù)據(jù)格式轉(zhuǎn)換,音頻文件讀寫,音頻流解析,插件工作支持等。
它位于框架 AudioToolbox 中。
負(fù)責(zé)音頻數(shù)據(jù)格式的轉(zhuǎn)換
它位于框架 AudioToolbox 中。
負(fù)責(zé)音頻數(shù)據(jù)的讀寫。
它位于框架 AudioToolbox 中。
支持均衡器和混音器等數(shù)字信號(hào)處理的插件。
它位于框架 AudioToolbox 中。
負(fù)責(zé)流解析。
它位于框架 Core Audio 中。
負(fù)責(zé)音頻音頻時(shí)鐘同步。
該主要在MAC上的音頻APP實(shí)現(xiàn)中并且需要最大限度的實(shí)時(shí)性能的情況下使用,大部分音頻APP不需要使用該層的服務(wù)。而且,在iOS上也提供了具備較高實(shí)時(shí)性能的高層API達(dá)到你的需求。例如 OpenAL ,在游戲中具備與I/O直接調(diào)用的實(shí)時(shí)音頻處理能力。
它在 IOKit 框架中,與硬件驅(qū)動(dòng)交互。
獲得用戶空間訪問硬件設(shè)備和驅(qū)動(dòng)程序。 I / O Kit 框架通過設(shè)備接口機(jī)制實(shí)現(xiàn)對(duì)I / O Kit對(duì)象(驅(qū)動(dòng)程序和結(jié)點(diǎn))的非內(nèi)核訪問。
音頻硬件抽象層,使API調(diào)用與實(shí)際硬件相分離,保持獨(dú)立。
它位于 Core MIDI 框架中,與MIDI設(shè)備(如硬件鍵盤和合成器)進(jìn)行通信。
Core MIDI 框架提供了用于與MIDI(樂器數(shù)字接口)設(shè)備(包括硬件鍵盤和合成器)進(jìn)行通信的API。 使用基座連接器或網(wǎng)絡(luò)從iOS設(shè)備進(jìn)行連接。 有關(guān)使用基座連接器的更多信息,請(qǐng)參閱Apple的 MFi program 。
訪問電腦硬件時(shí)鐘。
只實(shí)現(xiàn)音頻的播放,沒有其他需求, AVAudioPlayer 就可以滿足需求。它的接口使用簡(jiǎn)單,不用關(guān)心其中的細(xì)節(jié),通常只提供給它一個(gè)播放源的URL地址,并且調(diào)用其play、pause、stop等方法進(jìn)行控制,observer其播放狀態(tài)更新UI即可。
APP需要對(duì)音頻進(jìn)行流播放,就需要 AudioFileStreamer 加 Audio Queue ,將網(wǎng)絡(luò)或者本地的流讀取到內(nèi)存,提交給 AudioFileStreamer 解析分離音頻幀,分離出來的音頻幀可以送給 AudioQueue 進(jìn)行解碼和播放,可參考下面。
AudioStreamer
FreeStreamer
AFSoundManager
APP需要需要對(duì)音頻施加音效(均衡器、混響器),就是除了數(shù)據(jù)的讀取和解析以外還需要用到AudioConverter或者Codec來把音頻數(shù)據(jù)轉(zhuǎn)換成PCM數(shù)據(jù),再由AudioUnit+AUGraph來進(jìn)行音效處理和播放,可參考下面。
DouAudioStreamer
TheAmazingAudioEngine
AudioKit
1. iOS Audio Unit(一)
可能在軟件某些時(shí)候需要震動(dòng)手機(jī)以示提醒,可能還要播放一段特殊的聲音引起用戶的注意,在ios中如何實(shí)現(xiàn)呢?
首先實(shí)現(xiàn)震動(dòng),其實(shí)就是調(diào)用系統(tǒng)的方法,一句話就行,AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);當(dāng)然前提是要加入AVFoundation.framework這個(gè)框架
然后實(shí)現(xiàn)播放聲音,可能還要循環(huán)播放多少次,循環(huán)播放用n次,[self.player setNumberOfLoops:n];
因?yàn)槲也シ诺穆曇羰莔p3,是用AudioToolbox框架,需要加入這個(gè)框架
代碼如下
ViewController.h文件
#import
#import
#import
@interface ViewController : UIViewController{
AVAudioPlayer *player;
}
@property (retain) AVAudioPlayer *player;
@end
ViewController.m文件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize player;
- (BOOL) prepAudio
{
NSError *error;
NSString *path = [[NSBundle mainBundle] pathForResource:@"loop" ofType:@"mp3"];
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) return NO;
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:error];
if (!self.player)
{
NSLog(@"Error: %@", [error localizedDescription]);
return NO;
}
[self.player prepareToPlay];
[self.player setNumberOfLoops:1];
return YES;
}
- (void)viewDidLoad
{
[self prepAudio];
[self.player play];
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
@end
下載源代碼
?項(xiàng)目中應(yīng)產(chǎn)品的需求,需給button添加點(diǎn)擊聲音。下面我總結(jié)了一下關(guān)于播放系統(tǒng)提示音和播放自定義聲音的方法。
一:播放系統(tǒng)提示音。
第一步:首先得導(dǎo)入AudioToolbox框架? #importAudioToolbox/AudioToolbox.h
第二步:定義一個(gè)SystemSoundIDSystemSoundID soundID =1000;
? ? ? ? ?AudioServicesPlaySystemSound(soundID);
SystemSoundID具體參數(shù)請(qǐng)參考 傳送門
二:播放本地文件
//得到音效文件的地址
NSString*soundFilePath =[[NSBundlemainBundle]pathForResource:nameofType:type];
//將地址字符串轉(zhuǎn)換成url
NSURL*soundURL = [NSURLfileURLWithPath:soundFilePath];
//生成系統(tǒng)音效id
AudioServicesCreateSystemSoundID((__bridgeCFURLRef)soundURL, soundFileObject);
//播放系統(tǒng)音效
AudioServicesPlaySystemSound(soundFileObject);