2024-07-22

//

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

//是否開始有拉取到第一段數(shù)據(jù)了

@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];

? ? //這里為了方便測試,再次點(diǎn)擊下載,如果發(fā)現(xiàn)downLoadingPath存在,那就刪除掉

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

? ? ? ? [XMGFileTool removeFile:self.downLoadingPath];

? ? }



? ? // 從0字節(jié)開始請求資源

? ? [self downLoadWithURL:url offset:0];


}

#pragma mark- 協(xié)議方法

// 第一次接受到相應(yīng)的時(shí)候調(diào)用(響應(yīng)頭, 并沒有具體的資源內(nèi)容)

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

? ? // 繼續(xù)接受數(shù)據(jù)

? ? // 確定開始下載數(shù)據(jù)

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

? ? [self.outputStream open];

? ? completionHandler(NSURLSessionResponseAllow);


}

static NSInteger i = 0;

//下載到資源了,多次調(diào)用,直到下載完畢

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

{


? ? //下載數(shù)據(jù)寫進(jìn)downLoadingPath

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

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

? ? ? ? if(self.isStarDownloadData == NO) {

? ? ? ? ? ? self.isStarDownloadData = YES;

? ? ? ? ? ? //這里我也不知道為啥調(diào)用一次,就能把那么長一首歌全播下來,按理來說,這里會多次收到下載數(shù)據(jù),應(yīng)該是一小段一小段數(shù)據(jù)下載下來的.理論上應(yīng)該一開始只播放幾秒. 所以猜測可能和NSOutputStream這種流的方式寫入文件有關(guān)系.? 如果用[data WriteToFile]這種就不行

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

? ? ? ? }

? ? }


? ? NSLog(@"在接受后續(xù)數(shù)據(jù)%ld",data.length);


}

// 請求完成的時(shí)候調(diào)用( != 請求成功/失敗)

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


? ? NSLog(@"請求完成");


? ? if(error ==nil) {

? ? ? ? // 不一定是成功

? ? ? ? // 數(shù)據(jù)是肯定可以請求完畢

? ? ? ? // 判斷, 本地緩存 == 文件總大小 {filename: filesize: md5:xxx}

? ? ? ? // 如果等于 => 驗(yàn)證, 是否文件完整(file md5 )

? ? }else{

? ? ? ? NSLog(@"有問題");

? ? }


? ? [self.outputStream close];




}

#pragma mark- 私有方法

/**

?根據(jù)開始字節(jié), 請求資源


?@param url url

?@param offset 開始字節(jié)

?*/

- (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, 默認(rèn)情況, 掛起狀態(tài)

? ? 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];


? ? // 安裝音頻緩沖區(qū)的處理

? ? 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,如進(jìn)度條或波動圖

? ? ? ? });

? ? }

}




#pragma mark - XMGDownLoaderDelegate

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

? ? NSURL*url = [NSURLfileURLWithPath:path];

? ? [selfplayWithUrl:url];


}

@end

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

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

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