【iOS】音频系统方法格式转换,获取音频信息获取

直接上代码

  • .h
#import <MobileCoreServices/MobileCoreServices.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AudioUnit/AudioUnit.h>
#import <AVFoundation/AVFoundation.h>

/// ogg,amr,acc 格式无法使用
@interface YSAudioTool : NSObject
+ (AudioFileID)getAudioFileID:(NSURL *)fileUrl;
+ (NSDictionary *)getAuidoBaseInfo:(AudioFileID)audioId;
+ (NSString *)getFileFormat:(AudioFileID)audioId showNormalType:(BOOL)flag;
+ (void)playAuido:(NSURL *)fileUrl;
@end
  • .m
#import "YSAudioTool.h"

@interface YSAudioTool()
+ (NSString *)fileFormatCovert:(NSString*)file;
@end

@implementation YSAudioTool

+ (AudioFileID)getAudioFileID:(NSURL *)fileUrl {
    AudioFileID fileID;
    AudioFileOpenURL((__bridge CFURLRef)fileUrl, kAudioFileReadWritePermission,
                     kAudioFileWAVEType, &fileID);
    return fileID;
}

/// 获取音频信息, 编码.声道数.采样率
/// @param audioId  音频文件id
+ (NSDictionary *)getAuidoBaseInfo:(AudioFileID)audioId {
    NSMutableDictionary * result = [NSMutableDictionary new];
    UInt32 formatListSize = 0;
    OSStatus status = AudioFileGetPropertyInfo(audioId, kAudioFilePropertyFormatList, &formatListSize, NULL);
    if (status == noErr) {
        AudioFormatListItem *formatList = (AudioFormatListItem *)malloc(formatListSize);
        status = AudioFileGetProperty(audioId, kAudioFilePropertyFormatList, &formatListSize, formatList);
        for (int i = 0; i * sizeof(AudioFormatListItem) < formatListSize; i += sizeof(AudioFormatListItem))
        {
            AudioStreamBasicDescription pasbd = formatList[i].mASBD;
            //选择需要的格式。。
            switch (pasbd.mFormatID) {
                case kAudioFormatAC3:
                    result[@"acodec"] = @"aac";
                    break;
                case kAudioFormatOpus:
                    result[@"acodec"] = @"opus";
                    break;
                case kAudioFormatLinearPCM:
                    result[@"acodec"] = @"pcm";
                    break;
                case kAudioFormatMPEGLayer3:
                    result[@"acodec"] = @"mp3";
                    break;
                default:
                    result[@"acodec"] = @"unknow";
                    break;
            }
            UInt32 channel = pasbd.mChannelsPerFrame;   // 声道
            result[@"channelNumber"] = @(channel);
            result[@"sampleRate"] = @(pasbd.mSampleRate);
            free(formatList);
        }
    }
    return result;
}

/// 获取音频 文件类型
/// @param audioId  音频文件id
+ (NSString *)getFileFormat:(AudioFileID)audioId showNormalType:(BOOL)flag {
    char * result ;
    UInt32 formatListSize = 0;
    OSStatus status = AudioFileGetPropertyInfo(audioId, kAudioFilePropertyFileFormat, &formatListSize, NULL);
    result = (char *)malloc(formatListSize);
    status = AudioFileGetProperty(audioId, kAudioFilePropertyFileFormat, &formatListSize, result);
    NSMutableString *tranformFormat = [NSMutableString new];
    for (long i = strlen(result) -1; i >= 0; i--) {
        [tranformFormat appendFormat:@"%c", result[i]];
    }
    if (flag) {
        return [YSAudioTool fileFormatCovert:tranformFormat];
    }
    return tranformFormat;
}

+ (NSString *)fileFormatCovert:(NSString*)file {
    NSDictionary *params = @{
        @"MPG3": @"mp3",
        @"WAVE": @"wav",
        @"MPG3": @"mp3"
    };
    return params[file];
}

+ (void)playAuido:(NSURL *)fileUrl {
    SystemSoundID soundID;
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)fileUrl, &soundID);
    AudioServicesPlaySystemSound(soundID);
}


/**
 把mp3->wav; wav->wav;格式(ogg 不能转换,acc 不能转换)
 @param originalUrlStr .m4a文件路径
 @param destUrlStr .wav文件路径
 @param completed 转化完成的block
 */
+ (void)convetM4aToWav:(NSString *)originalUrlStr
               destUrl:(NSString *)destUrlStr
             completed:(void (^)(NSError *error)) completed {

    if ([[NSFileManager defaultManager] fileExistsAtPath:destUrlStr]) {
        [[NSFileManager defaultManager] removeItemAtPath:destUrlStr error:nil];
    }
    NSURL *originalUrl = [NSURL fileURLWithPath:originalUrlStr];
    NSURL *destUrl     = [NSURL fileURLWithPath:destUrlStr];
    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:originalUrl options:nil];
    NSLog(@"finallUrl: %@", destUrl);
    //读取原始文件信息
    NSError *error = nil;
    AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset error:&error];
    NSArray<AVMetadataItem *> *a = assetReader.asset.metadata;
    for (int i = 0; i < a.count; i++) {
        NSString* type =  a[i].dataType;
        NSLog(@"%@", type);
    }

    NSArray<AVMetadataFormat> * b = assetReader.asset.availableMetadataFormats;
    for (int i = 0; i < b.count; i++) {
        NSString* type =  b[i].pathExtension;
        NSLog(@"%@", type);
    }

    AVMediaSelection *selection = assetReader.asset.preferredMediaSelection;
    NSArray<AVMetadataItem *> *c = selection.asset.metadata;
    for (int i = 0; i < a.count; i++) {
        NSString* type =  c[i].dataType;
        NSLog(@"%@", type);
    }
    // 采样率
    CMTimeScale sample = assetReader.asset.duration.timescale;
    NSLog(@"asdfasdfsdf %d", sample);
    if (songAsset.tracks.count <= 0) {
        return;
    }
    AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput
                                              assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks
                                              audioSettings: nil];
    if (![assetReader canAddOutput:assetReaderOutput]) {
        NSLog(@"can't add reader output... die!");
        completed(error);
        return;
    }
    [assetReader addOutput:assetReaderOutput];

    AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:destUrl
                                                          fileType:AVFileTypeWAVE
                                                             error:&error];
    if (error) {
        NSLog(@"error: %@", error);
        completed(error);
        return;
    }
    AudioChannelLayout channelLayout;
    memset(&channelLayout, 0, sizeof(AudioChannelLayout));
    channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
    NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                    [NSNumber numberWithFloat:8000], AVSampleRateKey,
                                    [NSNumber numberWithInt:1], AVNumberOfChannelsKey,
                                    [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                    [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                    [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                    [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
                                    nil];

    AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio
                                                                              outputSettings:outputSettings];
    if ([assetWriter canAddInput:assetWriterInput]) {
        [assetWriter addInput:assetWriterInput];
    } else {
        NSLog(@"can't add asset writer input... die!");
        if (completed != nil) {
            completed(error);
        }
        return;
    }

    assetWriterInput.expectsMediaDataInRealTime = NO;

    [assetWriter startWriting];
    [assetReader startReading];

    AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
    CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
    [assetWriter startSessionAtSourceTime:startTime];

    __block UInt64 convertedByteCount = 0;

    dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
    [assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue
                                            usingBlock: ^
     {
         while (assetWriterInput.readyForMoreMediaData) {
             CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
             if (nextBuffer) {
                 // append buffer
                 [assetWriterInput appendSampleBuffer: nextBuffer];
                 NSLog(@"appended a buffer (%zu bytes)",
                        CMSampleBufferGetTotalSampleSize (nextBuffer));
                 convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);


             } else {
                 [assetWriterInput markAsFinished];
                 [assetWriter finishWritingWithCompletionHandler:^{

                 }];
                 [assetReader cancelReading];
                 NSDictionary *outputFileAttributes = [[NSFileManager defaultManager]
                                                       attributesOfItemAtPath:[destUrl path]
                                                       error:nil];
                 NSLog(@"FlyElephant %lld",[outputFileAttributes fileSize]);
                 break;
             }
         }
         NSLog(@"转换结束");
         // 删除临时temprecordAudio.m4a文件
         NSError *removeError = nil;
         if ([[NSFileManager defaultManager] fileExistsAtPath:originalUrlStr]) {
             BOOL success = [[NSFileManager defaultManager] removeItemAtPath:originalUrlStr error:&removeError];
             if (!success) {
                 NSLog(@"删除临时temprecordAudio.m4a文件失败:%@",removeError);
                 completed(removeError);
             }else{
                 NSLog(@"删除临时temprecordAudio.m4a文件:%@成功",originalUrlStr);
                 if (completed != nil) {
                     completed(removeError);
                 }
             }
         }
     }];
}

@end

您的一举一动都是对我的莫大支持

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值