iOS:語音播報本地音頻拆分合成播放實現(xiàn)

封裝相關(guān)播放文件LCAudioPlayManager,項目中導(dǎo)入錄好的0,1,2,3,4,5,6,7,8,9,點,十百,千,萬,元,user_payment(描述內(nèi)容,例如“支付寶到賬”),cancel_payment(“用戶取消支付”)等音頻文件,mp3或者wav都可以。

LCAudioPlayManager.h文件

#import <Foundation/Foundation.h>

@interface LCAudioPlayManager : NSObject

+ (instancetype)sharedInstance;

// 先處理金額,得到語音文件的數(shù)組

-(NSArray *)getMusicArrayWithNum:(NSString *)numStr;

- (void)hecheng:(NSArray*)fileNameArray;

/// 系統(tǒng)的語音播報(紅包消息)

/// AVSpeechSynthesizer(iOS10.0-12.0),之后不支持播報

- (void)speechWalllentMessage:(NSString *)numStr;

@end


LCAudioPlayManager.m文件

#import "LCAudioPlayManager.h"

#import?<AVFoundation/AVFoundation.h>

@implementation LCAudioPlayManager

+ (instancetype)sharedInstance{

? ? static?LCAudioPlayManager * _instance =nil;

? ? static?dispatch_once_t onceToken ;

? ? dispatch_once(&onceToken, ^{

? ? ? ? _instance = [[LCAudioPlayManager alloc]init] ;

? ? }) ;

? ? return?_instance;

}

- (void)hecheng:(NSArray*)fileNameArray{

? ? /************************合成音頻并播放*****************************/

? ? NSMutableArray*audioAssetArray = [[NSMutableArray alloc]init];

? ? NSMutableArray*durationArray = [[NSMutableArray alloc]init];

? ? [durationArray addObject:@(0)];

? ? AVMutableComposition *composition = [AVMutableComposition composition];

? ? CMTime allTime =kCMTimeZero;

? ? for(NSInteger i =0; i < fileNameArray.count; i++) {

? ? ? ? NSString*auidoPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",fileNameArray[I]] ofType:@"wav"];

? ? ? ? AVURLAsset*audioAsset = [AVURLAsset assetWithURL:[NSURL ?fileURLWithPath:auidoPath]];

? ? ? ? [audioAsset ArrayaddObject:audioAsset];

? ? ? ? // 音頻軌道

? ? ? ? AVMutableCompositionTrack *audioTrack = [composition ? ?addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:0];

? ? ? ? //音頻素材軌道

? ? ? ? AVAssetTrack*audioAssetTrack = [[audioAsset ? tracksWithMediaType:AVMediaTypeAudio]firstObject];

? ? ? ? //音頻合并-插入音軌文件

? ? ? ? [audioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) ?ofTrack:audioAssetTrack atTime:allTime error:nil];

? ? ? ? //更新當(dāng)前的位置

? ? ? ? allTime =CMTimeAdd(allTime, audioAsset.duration);

? ? }

? ? //合并后的文件導(dǎo)出- `presetName`要和之后的`session.outputFileType`相對應(yīng)。

? ? AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetAppleM4A];

? ? NSString *outPutFilePath = [[NSHomeDirectory() ?stringByAppendingPathComponent:@"Documents"]? stringByAppendingPathComponent:@"test.m4a"];

? ? if([[NSFileManager defaultManager]fileExistsAtPath:outPutFilePath]) {

? ? ? ? [[NSFileManager defaultManager] removeItemAtPath:outPutFilePath error:nil];

? ? }

? ? //查看當(dāng)前session支持的fileType類型

? ? NSLog(@"---%@",[session supportedFileTypes]);

? ? session.outputURL= [NSURL fileURLWithPath:outPutFilePath];

? ? session.outputFileType = AVFileTypeAppleM4A; //與上述的`present`相對應(yīng)

? ? session.shouldOptimizeForNetworkUse = YES;? //優(yōu)化網(wǎng)絡(luò)

? ? [session exportAsynchronouslyWithCompletionHandler:^{

? ? ? ? NSLog(@"+++%@",[NSThread currentThread]);

? ? ? ? if (session.status == AVAssetExportSessionStatusCompleted) {

? ? ? ? ? ? NSLog(@"合并成功----%@", outPutFilePath);

? ? ? ? ? ? NSURL*url = [NSURL fileURLWithPath:outPutFilePath];

? ? ? ? ? ? static?SystemSoundIDsoundID =0;

? ? ? ? ? ? AudioServicesCreateSystemSoundID((__bridge?CFURLRef?_Nonnull)(url), &soundID);

? ? ? ? ? ? AudioServicesPlayAlertSoundWithCompletion(soundID, ^{

? ? ? ? ? ? ? ? NSLog(@"播放完成");

? ? ? ? ? ? ? ? AudioServicesDisposeSystemSoundID(soundID);

? ? ? ? ? ? });

? ? ? ? }else{

? ? ? ? ? ? //其他情況,具體請看這里`AVAssetExportSessionStatus`.

? ? ? ? }

? ? }];

}

-(NSArray *)getMusicArrayWithNum:(NSString *)numStr

{

? ? NSString*finalStr = [self?caculateNumber:numStr];

? ? //前部分字段例如:***到賬? user_payment是項目自定義的音樂文件

? ? NSMutableArray *finalArr = [[NSMutableArray alloc] initWithObjects:@"user_payment", ?nil];

? ? for(int?i=0; i

? ? ? ? [finalArr addObject:[finalStr substringWithRange:NSMakeRange(i,1)]];

? ? }

? ? return?finalArr;

}

-(NSString*)caculateNumber:(NSString*)numstr {

? ? NSArray *numberchar = @[@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"];

? ? NSArray*inunitchar =@[@"",@"十",@"百",@"千"];

? ? NSArray*unitname? =@[@"",@"萬",@"億"];

? ? NSString*valstr =[NSString stringWithFormat:@"%.2f",numstr.doubleValue] ;

? ? NSString*prefix =@"";

? ? // 將金額分為整數(shù)部分和小數(shù)部分

? ? NSString*head = [valstr substringToIndex:valstr.length-2-1] ;

? ? NSString*foot = [valstr substringFromIndex:valstr.length-2] ;

? ? //處理整數(shù)部分

? ? if([head isEqualToString:@"0"]) {

? ? ? ? prefix =@"0";

? ? }else{

? ? ? ? NSMutableArray *ch = [[NSMutableArray alloc]init] ;

? ? ? ? for(int?i =0; i < head.length; i++) {

? ? ? ? ? ? NSString* str = [NSString stringWithFormat:@"%x",[head characterAtIndex:i]-'0'] ;

? ? ? ? ? ? [ch addObject:str] ;

? ? ? ? }

? ? ? ? int?zeronum =0;

? ? ? ? for(int?i =0; i < ch.count; i++) {

? ? ? ? ? ? NSInteger index = (ch.count-1- i)%4;? ? ? //取段內(nèi)位置

? ? ? ? ? ? NSInteger indexloc = (ch.count-1- i)/4;? ? //取段位置

? ? ? ? ? ? if ([[ch objectAtIndex:i] isEqualToString:@"0"]) {

? ? ? ? ? ? ? ? zeronum ++ ;

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? if(zeronum !=0) {

? ? ? ? ? ? ? ? ? ? if(index !=3) {

? ? ? ? ? ? ? ? ? ? ? ? prefix=[prefix stringByAppendingString:@"零"];

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? zeronum =0;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if(ch.count>i) {

? ? ? ? ? ? ? ? ? ? NSInteger numIndex = [[ch objectAtIndex:i] intValue];

? ? ? ? ? ? ? ? ? ? if(numberchar.count>numIndex) {

? ? ? ? ? ? ? ? ? ? ? ? prefix = [prefix stringByAppendingString:[numberchar ? objectAtIndex:numIndex]] ;

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? if(inunitchar.count>index) {

? ? ? ? ? ? ? ? ? ? prefix = [prefix stringByAppendingString:[inunitchar objectAtIndex:index]] ;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? if(index ==0&& zeronum <4) {

? ? ? ? ? ? ? ? if(unitname.count>indexloc) {

? ? ? ? ? ? ? ? ? ? prefix = [prefix stringByAppendingString:[unitname objectAtIndex:indexloc]] ;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? //1十開頭的改為十

? ? ? if([prefix hasPrefix:@"1十"]) {

? ? ? ? ? prefix = [prefix stringByReplacingOccurrencesOfString:@"1十" withString:@"十"] ;

? ? ? }

? ? //處理小數(shù)部分

? ? if([foot isEqualToString:@"00"]) {

? ? ? ? prefix = [prefix stringByAppendingString:@"元"] ;

? ? }else{

? ? ? ? prefix = [prefix stringByAppendingString:[NSString stringWithFormat:@"點%@元", foot]] ;

? ? }

? ? return?prefix ;

}

#pragma mark iOS12.1以下 播放語音

?//語音播報紅包消息

- (void)speechWalllentMessage:(NSString *)numStr {

? ? //播放語音

? ? // 合成器 控制播放,暫停

? ? AVSpeechSynthesizer*_synthesizer;

? ? // 實例化說話的語言,說中文、英文

? ? AVSpeechSynthesisVoice *_voice;

? ? _voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-TW"];//zh_CN

? ? // 要朗誦,需要一個語音合成器

? ? _synthesizer = [[AVSpeechSynthesizer alloc]init];

? ? AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:[NSString stringWithFormat:@"%@",numStr]];

? ? //指定語音,和朗誦速度

? ? utterance.voice= _voice;

? ? utterance.rate=0.53;//0.6//越大語速越快

? ? utterance.pitchMultiplier = 1.2f;? //改變音調(diào)//1.0f 0.5-2,1一下男聲,以上女生

? ? utterance.volume=1;

? ? //啟動

? ? [_synthesizer speakUtterance:utterance];

}

@end


在需要播報的地方調(diào)用#import "LCAudioPlayManager.h"

NSArray *musicArr = [[LCAudioPlayManager sharedInstance] getMusicArrayWithNum:amountStr];

//amountStr是金額例:100 ?其他封裝文件做了相應(yīng)處理

[[LCAudioPlayManagersharedInstance]hecheng:musicArr];


//系統(tǒng)自帶語音合成調(diào)用

[[LCAudioPlayManager sharedInstance] speechWalllentMessage:contentStr];

//contentStr需要播報的文字內(nèi)容,例:“支付寶到賬100.01元”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容