美文网首页
2024-07-22

2024-07-22

作者: Torres_tang | 来源:发表于2024-08-12 07:51 被阅读0次

    //

    //  XMGDownLoader.h

    //  XMGDownLoader

    //

    //  Created by 小码哥 on 2017/1/8.

    //  Copyright © 2017年 xmg. All rights reserved.

    //

    #import

    @protocol XMGDownLoaderDelegate <NSObject>

    - (void)downloadData:(NSData*)datapath:(NSString*)path;

    @end

    @interface XMGDownLoader : NSObject

    - (void)downLoader:(NSURL*)url;

    @property (nonatomic, weak) id<XMGDownLoaderDelegate> delegate;

    @end

    //

    //  XMGDownLoader.m

    //  XMGDownLoader

    //

    //  Created by 小码哥 on 2017/1/8.

    //  Copyright © 2017年 xmg. All rights reserved.

    //

    #import "XMGDownLoader.h"

    #import "XMGFileTool.h"

    #define kTmpPath NSTemporaryDirectory()

    @interface XMGDownLoader () <NSURLSessionDataDelegate>

    @property (nonatomic, strong) NSURLSession *session;

    @property (nonatomic, copy) NSString *downLoadingPath;

    @property (nonatomic, strong) NSOutputStream *outputStream;

    //是否开始有拉取到第一段数据了

    @property (nonatomic, assign) BOOL isStarDownloadData;

    @end

    @implementation XMGDownLoader

    - (instancetype)init {

        if(self= [superinit]) {

        }

        return self;

    }

    - (NSURLSession *)session {

        if(!_session) {

            NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

            _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

        }

        return _session;

    }

    - (void)downLoader:(NSURL*)url {

        self.isStarDownloadData = NO;

        NSString*fileName = url.lastPathComponent;

        self.downLoadingPath = [kTmpPath stringByAppendingPathComponent:fileName];

        //这里为了方便测试,再次点击下载,如果发现downLoadingPath存在,那就删除掉

        if ([XMGFileTool fileExists:self.downLoadingPath]) {

            [XMGFileTool removeFile:self.downLoadingPath];

        }

        // 从0字节开始请求资源

        [self downLoadWithURL:url offset:0];

    }

    #pragma mark- 协议方法

    // 第一次接受到相应的时候调用(响应头, 并没有具体的资源内容)

    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {

        // 继续接受数据

        // 确定开始下载数据

        self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.downLoadingPath append:YES];

        [self.outputStream open];

        completionHandler(NSURLSessionResponseAllow);

    }

    static NSInteger i = 0;

    //下载到资源了,多次调用,直到下载完毕

    - (void)URLSession:(NSURLSession*)sessiondataTask:(NSURLSessionDataTask*)dataTaskdidReceiveData:(NSData*)data

    {

        //下载数据写进downLoadingPath

        [self.outputStream write:data.bytes maxLength:data.length];

        if(self.delegate&& [self.delegaterespondsToSelector:@selector(downloadData:path:)]) {

            if(self.isStarDownloadData == NO) {

                self.isStarDownloadData = YES;

                //这里我也不知道为啥调用一次,就能把那么长一首歌全播下来,按理来说,这里会多次收到下载数据,应该是一小段一小段数据下载下来的.理论上应该一开始只播放几秒. 所以猜测可能和NSOutputStream这种流的方式写入文件有关系.  如果用[data WriteToFile]这种就不行

                [self.delegate downloadData:data path:self.downLoadingPath];

            }

        }

        NSLog(@"在接受后续数据%ld",data.length);

    }

    // 请求完成的时候调用( != 请求成功/失败)

    - (void)URLSession:(NSURLSession*)sessiontask:(NSURLSessionTask*)taskdidCompleteWithError:(NSError*)error {

        NSLog(@"请求完成");

        if(error ==nil) {

            // 不一定是成功

            // 数据是肯定可以请求完毕

            // 判断, 本地缓存 == 文件总大小 {filename: filesize: md5:xxx}

            // 如果等于 => 验证, 是否文件完整(file md5 )

        }else{

            NSLog(@"有问题");

        }

        [self.outputStream close];

    }

    #pragma mark- 私有方法

    /**

     根据开始字节, 请求资源

     @param url url

     @param offset 开始字节

     */

    - (void)downLoadWithURL:(NSURL*)urloffset:(longlong)offset {

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:0];

        [requestsetValue:[NSString stringWithFormat:@"bytes=%lld-", offset] forHTTPHeaderField:@"Range"];

        // session 分配的task, 默认情况, 挂起状态

        NSURLSessionDataTask*dataTask = [self.sessiondataTaskWithRequest:request];

        [dataTaskresume];

    }

    @end

    //

    //  XMGFileTool.h

    //  XMGDownLoader

    //

    //  Created by 小码哥 on 2017/1/8.

    //  Copyright © 2017年 xmg. All rights reserved.

    //

    #import

    @interface XMGFileTool : NSObject

        + (BOOL)fileExists:(NSString*)filePath;

        + (longlong)fileSize:(NSString*)filePath;

        + (void)moveFile:(NSString*)fromPathtoPath:(NSString*)toPath;

        + (void)removeFile:(NSString*)filePath;

    @end

    //

    //  XMGFileTool.m

    //  XMGDownLoader

    //

    //  Created by 小码哥 on 2017/1/8.

    //  Copyright © 2017年 xmg. All rights reserved.

    //

    #import "XMGFileTool.h"

    @implementation XMGFileTool

        + (BOOL)fileExists:(NSString*)filePath {

            if(filePath.length==0) {

                returnNO;

            }

            return [[NSFileManager defaultManager] fileExistsAtPath:filePath];

        }

        + (longlong)fileSize:(NSString*)filePath {

            if(![selffileExists:filePath]) {

                return0;

            }

           NSDictionary *fileInfo = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];

            return[fileInfo[NSFileSize]longLongValue];

        }

        + (void)moveFile:(NSString*)fromPathtoPath:(NSString*)toPath {

            if(![selffileSize:fromPath]) {

                return;

            }

            [[NSFileManager defaultManager] moveItemAtPath:fromPath toPath:toPath error:nil];

        }

        + (void)removeFile:(NSString*)filePath {

            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];

        }

    @end

    //

    //  ViewController.m

    //  XMGDownLoader

    //

    //  Created by 小码哥 on 2017/1/8.

    //  Copyright © 2017年 xmg. All rights reserved.

    //

    #import "ViewController.h"

    #import "XMGDownLoader.h"

    #import

    @interface ViewController ()<XMGDownLoaderDelegate>

    @property (nonatomic, strong) XMGDownLoader *downLoader;

    @property (nonatomic, strong) AVAudioEngine *engine;

    @property (nonatomic, strong) AVAudioPlayerNode *playerNode;

    @end

    @implementation ViewController

    - (XMGDownLoader *)downLoader {

        if (!_downLoader) {

            _downLoader= [XMGDownLoadernew];

            _downLoader.delegate = self;

        }

        return _downLoader;

    }

    - (void)viewDidLoad {

        [super viewDidLoad];

        self.engine= [[AVAudioEnginealloc]init];

        self.playerNode = [[AVAudioPlayerNode alloc] init];

        [self.engine attachNode:self.playerNode];

        [self.engine connect:self.playerNode to:self.engine.mainMixerNode format:nil];

        // 安装音频缓冲区的处理

        AVAudioFormat *format = [self.engine.mainMixerNode inputFormatForBus:0];

        [self.playerNodeinstallTapOnBus:0bufferSize:4096format:formatblock:^(AVAudioPCMBuffer*buffer,AVAudioTime*when) {

            [selfprocessAudioBuffer:buffer];

        }];

        NSError*error =nil;

        if(![self.enginestartAndReturnError:&error]) {

            NSLog(@"Audio Engine error: %@", error.localizedDescription);

        }

        [self.playerNode play];

        // Do any additional setup after loading the view.

        UIButton*btn = [[UIButtonalloc]initWithFrame:CGRectMake(0,100,100,100)];

        btn.backgroundColor = [UIColor redColor];

        [btnsetTitle:@"下载播放" forState:UIControlStateNormal];

        [btnaddTarget:self action:@selector(downAndPlayAudio) forControlEvents:UIControlEventTouchUpInside];

        [self.view addSubview:btn];

    }

    - (void)downAndPlayAudio {

        NSURL *url1 = [NSURL URLWithString:@"http://cdnringhs.shoujiduoduo.com/ringres/userv1/m96/482/317324482.mp3"];//短mp3音频

        NSURL *url2 = [NSURL URLWithString:@"http://cdnringhs.shoujiduoduo.com/ringres/userv1/m96/290/315379290.mp3"];//长mp3音频

        [self.downLoader downLoader:url2];

    }

    - (void)playWithUrl:(NSURL*)url {

        NSError*error =nil;

        AVAudioFile*file = [[AVAudioFilealloc]initForReading:urlerror:&error];

        if(error) {

            NSLog(@"Audio file error: %@", error.localizedDescription);

            return;

        }

        [self.playerNode scheduleFile:file atTime:nil completionHandler:^{

            NSLog(@"播放完成");

        }];

    }

    - (void)processAudioBuffer:(AVAudioPCMBuffer *)buffer {

        AVAudioChannelCountchannelCount = buffer.format.channelCount;

        if(channelCount >0) {

            float*channelData = buffer.floatChannelData[0];

            NSUIntegerframeLength = buffer.frameLength;

            NSMutableArray *channelDataArray = [NSMutableArrayarrayWithCapacity:frameLength];

            for(NSUIntegeri =0; i < frameLength; i++) {

                [channelDataArrayaddObject:@(channelData[i])];

            }

            floatrms =0;

            for(NSNumber*valueinchannelDataArray) {

                rms += value.floatValue* value.floatValue;

            }

            rms =sqrt(rms / frameLength);

            floatavgPower =20*log10(rms);

            dispatch_async(dispatch_get_main_queue(), ^{

    //            NSLog(@"Current audio power: %f dB", avgPower);

                // 你可以在这里更新UI,如进度条或波动图

            });

        }

    }

    #pragma mark - XMGDownLoaderDelegate

    - (void)downloadData:(NSData*)datapath:(NSString*)path {

        NSURL*url = [NSURLfileURLWithPath:path];

        [selfplayWithUrl:url];

    }

    @end

    相关文章

      网友评论

          本文标题:2024-07-22

          本文链接:https://www.haomeiwen.com/subject/bvqehjtx.html