2024-07-22

2024-08-12  本文已影响0人  Torres_tang

//

//  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

上一篇 下一篇

猜你喜欢

热点阅读