MidiPlayerEngine.m 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. //
  2. // MidiPlayerEngine.m
  3. // MidiPlayer
  4. //
  5. // Created by Kyle on 2021/11/30.
  6. //
  7. #import "MidiPlayerEngine.h"
  8. #import <AVFoundation/AVFoundation.h>
  9. #import <CoreAudio/CoreAudioTypes.h>
  10. #import "CoreAudioUtils.h"
  11. #import "GCDTimer.h"
  12. @interface MidiPlayerEngine ()
  13. @property (readwrite) AUNode pitchNode;
  14. @property (readwrite) AudioUnit pitchUnit;
  15. @property (readwrite) AUGraph processingGraph;
  16. @property (readwrite) AUNode samplerNode;
  17. @property (readwrite) AUNode ioNode;
  18. @property (readwrite) AUNode mixerNode;
  19. @property (readwrite) AudioUnit samplerUnit;
  20. @property (readwrite) AudioUnit mixerUnit;
  21. @property (readwrite) AudioUnit ioUnit;
  22. @property (nonatomic) NSMutableArray* samplerNodeList;
  23. @property (nonatomic) NSMutableArray* samplerUnitList;
  24. @property (nonatomic) MusicPlayer musicPlayer;
  25. @property (nonatomic) MusicSequence musicSequence;
  26. @property (nonatomic) MusicTrack musicTrack;
  27. @property (nonatomic) UInt32 trackCount;
  28. @property (nonatomic) BOOL playing;
  29. @property (readwrite) double totalTime;
  30. @property (nonatomic) double currentTime;
  31. @property (nonatomic) Boolean isMute;
  32. @property (nonatomic) Boolean muteDrum;
  33. @property (nonatomic) NSMutableArray* instrumentArray;
  34. @property (nonatomic) double timeRatio;
  35. @property (nonatomic, strong) NSString *soundFileUrl;
  36. @property (nonatomic, strong) MidiPlayerEngine *clickPlayer;
  37. @property (nonatomic, assign) BOOL isClickPlayer;
  38. @property (nonatomic, assign) MusicTimeStamp trackLength;
  39. @end
  40. @implementation MidiPlayerEngine
  41. - (instancetype)init {
  42. self = [super init];
  43. if (self) {
  44. [self configDefault];
  45. }
  46. return self;
  47. }
  48. - (void)configDefault {
  49. self.isMute = NO;
  50. self.muteDrum = NO;
  51. self.baseRate = 120.0f;
  52. self.timeRatio = 1.0;
  53. self.reportTime = 10;
  54. self.soundFileUrl = [[NSBundle mainBundle]
  55. pathForResource:@"synthgms" ofType:@"sf2"];
  56. self.accompanyVolume = 0.2f;
  57. }
  58. - (void)configSoundFilePath:(NSString *)filePath {
  59. self.soundFileUrl = filePath;
  60. }
  61. #pragma mark ---- audio setup
  62. - (BOOL)createAUGraph {
  63. CheckError(NewAUGraph(&_processingGraph), "NewAUGraph");
  64. /*
  65. * 创建节点
  66. * 1.添加音频器附件描述
  67. * 2.音频处理图根据器件描述生成1个节点
  68. * 节点数= track数
  69. */
  70. AudioComponentDescription desc = {0};
  71. desc.componentType = kAudioUnitType_MusicDevice;
  72. /* MIDI合成器,多声道附件*/
  73. desc.componentSubType = kAudioUnitSubType_MIDISynth;
  74. desc.componentManufacturer = kAudioUnitManufacturer_Apple;
  75. desc.componentFlags = 0;
  76. desc.componentFlagsMask = 0;
  77. for (int i = 0; i < self.trackCount; i++) {
  78. CheckError(AUGraphAddNode(self.processingGraph, &desc, &_samplerNode), "AUGraphAddNode");
  79. [self.samplerNodeList addObject:[NSString stringWithFormat:@"%d", (int)_samplerNode]];
  80. }
  81. /*
  82. * 创建混合器节点
  83. */
  84. AudioComponentDescription mixerUnitDescription = {0};
  85. mixerUnitDescription.componentType = kAudioUnitType_Mixer;
  86. mixerUnitDescription.componentSubType = kAudioUnitSubType_MultiChannelMixer;
  87. mixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
  88. mixerUnitDescription.componentFlags = 0;
  89. mixerUnitDescription.componentFlagsMask = 0;
  90. CheckError(AUGraphAddNode(self.processingGraph,
  91. &mixerUnitDescription,
  92. &_mixerNode),
  93. "AUGraphAddNode");
  94. // I/O unit
  95. /*
  96. 创建输出节点
  97. */
  98. AudioComponentDescription iOUnitDescription = {0};
  99. iOUnitDescription.componentType = kAudioUnitType_Output;
  100. iOUnitDescription.componentSubType = kAudioUnitSubType_RemoteIO;
  101. iOUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
  102. iOUnitDescription.componentFlags = 0;
  103. iOUnitDescription.componentFlagsMask = 0;
  104. CheckError(AUGraphAddNode(self.processingGraph,
  105. &iOUnitDescription,
  106. &_ioNode),
  107. "AUGraphAddNode");
  108. // 变调
  109. AudioComponentDescription pitchDesc = {0};
  110. pitchDesc.componentType = kAudioUnitType_FormatConverter;
  111. pitchDesc.componentSubType = kAudioUnitSubType_NewTimePitch;
  112. pitchDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
  113. pitchDesc.componentFlags = 0;
  114. pitchDesc.componentFlagsMask = 0;
  115. AUGraphAddNode(self.processingGraph, &pitchDesc, &_pitchNode);
  116. /*
  117. 打开AUGraph才能调用AUGraphNodeInfo获取节点对应的audio unit
  118. */
  119. CheckError(AUGraphOpen(self.processingGraph), "AUGraphOpen");
  120. /*
  121. 保存sampler对应的audio unit
  122. */
  123. for(int i = 0; i< self.trackCount; i++){
  124. CAudioUnit* sampleUnit = [[CAudioUnit alloc] init];
  125. AudioUnit audioUnit = sampleUnit.audioUnit;
  126. CheckError(AUGraphNodeInfo(self.processingGraph,
  127. [self.samplerNodeList[i] intValue],
  128. NULL,
  129. &audioUnit),
  130. "AUGraphNodeInfo");
  131. [self configMaxFramesPerSliceWithAudioUnit:audioUnit];
  132. sampleUnit.audioUnit = audioUnit;
  133. [self.samplerUnitList addObject:sampleUnit];
  134. NSURL *bankURL;
  135. /*
  136. 音色库
  137. */
  138. bankURL = [[NSURL alloc] initFileURLWithPath:self.soundFileUrl];
  139. // load sound bank
  140. CheckError(AudioUnitSetProperty(audioUnit,
  141. kMusicDeviceProperty_SoundBankURL,
  142. kAudioUnitScope_Global,
  143. 0,
  144. &bankURL,
  145. sizeof(bankURL)),
  146. "kAUSamplerProperty_LoadPresetFromBank");
  147. }
  148. /*
  149. 保存mixer对应的audio unit
  150. */
  151. CheckError(AUGraphNodeInfo(self.processingGraph,
  152. self.mixerNode,
  153. NULL,
  154. &_mixerUnit),
  155. "AUGraphNodeInfo");
  156. [self configMaxFramesPerSliceWithAudioUnit:_mixerUnit];
  157. /*
  158. 保存输出对应的audio unit
  159. */
  160. CheckError(AUGraphNodeInfo(self.processingGraph,
  161. self.ioNode,
  162. NULL,
  163. &_ioUnit),
  164. "AUGraphNodeInfo");
  165. [self configMaxFramesPerSliceWithAudioUnit:_ioUnit];
  166. /*
  167. 设置mixer输入的数量
  168. */
  169. UInt32 busCount = self.trackCount;
  170. //set the mixer unit`s bus count
  171. CheckError(AudioUnitSetProperty(_mixerUnit,
  172. kAudioUnitProperty_ElementCount,
  173. kAudioUnitScope_Input,
  174. 0,
  175. &busCount,
  176. sizeof(busCount)),
  177. "AudioUnitSetProperty_SetMixerInputCount");
  178. /*
  179. 设置mixer的采样率,44.1kHz是标准采样率
  180. */
  181. Float64 graphSampleRate = 44100.0;
  182. //set mixer unit`s output sample rate format
  183. CheckError(AudioUnitSetProperty(_mixerUnit,
  184. kAudioUnitProperty_SampleRate,
  185. kAudioUnitScope_Output,
  186. 0,
  187. &graphSampleRate,
  188. sizeof(graphSampleRate)),
  189. "AudioUnitSetProperty_SetMixerSampleRate");
  190. AudioUnitParameterValue defaultOutputVolume = 1.0;
  191. CheckError(AudioUnitSetParameter(_mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Output, 0, defaultOutputVolume, 0), "AudioUnitSetParameter(kMultiChannelMixerParam_Volume)");
  192. //connect samplers to mixer unit
  193. /*
  194. 将sampler unit的输出连到mixer的输入
  195. */
  196. for(int i = 0;i < self.trackCount;i++) {
  197. CheckError(AUGraphConnectNodeInput(self.processingGraph,
  198. [self.samplerNodeList[i] intValue],
  199. 0,
  200. self.mixerNode,
  201. i),
  202. "AUGraphConnectNodeInput_ConnectSamplersToMixerUnit");
  203. }
  204. /*
  205. 保存pitchNode对应的audio unit
  206. */
  207. AUGraphNodeInfo(self.processingGraph, self.pitchNode, &pitchDesc, &_pitchUnit);
  208. [self configMaxFramesPerSliceWithAudioUnit:_pitchUnit];
  209. AUGraphConnectNodeInput(self.processingGraph, self.mixerNode, 0, self.pitchNode, 0);
  210. //connect pitch to output unit
  211. /*
  212. 将pitch的输出连到remote I/O的输入
  213. */
  214. CheckError(AUGraphConnectNodeInput(self.processingGraph,
  215. self.pitchNode,
  216. 0,
  217. self.ioNode,
  218. 0),
  219. "AUGraphConnectNodeInput_ConnectMixerToOutput");
  220. NSLog (@"AUGraph is configured");
  221. return YES;
  222. }
  223. - (void)configMaxFramesPerSliceWithAudioUnit:(AudioUnit)audioUnit {
  224. AVAudioFrameCount maxFramesPerSlice = 4096;
  225. CheckError(AudioUnitSetProperty(audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFramesPerSlice, sizeof(maxFramesPerSlice)),"kAudioUnitProperty_MaximumFramesPerSlice");
  226. }
  227. - (void)startGraph {
  228. /*
  229. 音频处理图的初始化和开启
  230. */
  231. if (self.processingGraph) {
  232. Boolean outIsInitialized;
  233. CheckError(AUGraphIsInitialized(self.processingGraph,
  234. &outIsInitialized), "AUGraphIsInitialized");
  235. if(!outIsInitialized)
  236. CheckError(AUGraphInitialize(self.processingGraph), "AUGraphInitialize");
  237. Boolean isRunning;
  238. CheckError(AUGraphIsRunning(self.processingGraph,
  239. &isRunning), "AUGraphIsRunning");
  240. if(!isRunning)
  241. CheckError(AUGraphStart(self.processingGraph), "AUGraphStart");
  242. }
  243. }
  244. - (void)stopAUGraph {
  245. NSLog (@"Stopping audio processing graph");
  246. Boolean isRunning = false;
  247. CheckError(AUGraphIsRunning (self.processingGraph, &isRunning), "AUGraphIsRunning");
  248. if (isRunning) {
  249. CheckError(AUGraphStop(self.processingGraph), "AUGraphStop");
  250. self.playing = NO;
  251. }
  252. }
  253. - (void)setupAudioSession {
  254. AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  255. NSError *err = nil;
  256. AVAudioSessionCategory category = AVAudioSessionCategoryPlayAndRecord;
  257. if (@available(iOS 10.0, *)) {
  258. [audioSession setCategory:category mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionAllowBluetoothA2DP|AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionMixWithOthers error:&err];
  259. }
  260. else {
  261. [audioSession setCategory:category withOptions:AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionMixWithOthers error:&err];
  262. }
  263. [audioSession setActive:YES error:&err];
  264. }
  265. - (void)resumeAUGraph {
  266. if (self.processingGraph) {
  267. [self stopAUGraph];
  268. Boolean isRunning;
  269. CheckError(AUGraphIsRunning(self.processingGraph,
  270. &isRunning), "AUGraphIsRunning");
  271. if(!isRunning) {
  272. CheckError(AUGraphStart(self.processingGraph), "AUGraphStart");
  273. }
  274. }
  275. }
  276. #pragma mark --- Audio control
  277. - (BOOL)loadMIDIFileWithString:(NSString *)filePath {
  278. // 判断文件是否存在
  279. BOOL isExist = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
  280. if (isExist) {
  281. NSURL* midiFileURL = [[NSURL alloc] initFileURLWithPath:filePath];
  282. //新建MusicSequence
  283. CheckError(NewMusicSequence(&_musicSequence), "NewMusicSequence");
  284. NSData *midi_data = [NSData dataWithContentsOfURL:midiFileURL];
  285. //把文件加载到MusicSequence
  286. NSLog(@"----- start load file");
  287. // 提高加载速度 kMusicSequenceLoadSMF_ChannelsToTracks 会合并轨道 导致轨道速可能减少
  288. CheckError(MusicSequenceFileLoadData(self.musicSequence, (__bridge CFDataRef)midi_data, kMusicSequenceFile_MIDIType, kMusicSequenceLoadSMF_PreserveTracks), "MusicSequenceFileLoad");
  289. // NSLog(@"----- end load file");
  290. // CheckError(MusicSequenceFileLoad(self.musicSequence,
  291. // (__bridge CFURLRef) midiFileURL,
  292. // 0,
  293. // kMusicSequenceLoadSMF_ChannelsToTracks), "MusicSequenceFileLoad");
  294. NSLog(@"----- end load file");
  295. //读取MIDI文件轨道数量
  296. CheckError(MusicSequenceGetTrackCount(self.musicSequence, &_trackCount), "MusicSequenceGetTrackCount");
  297. NSLog(@"track ----%d",self.trackCount);
  298. [self createAUGraph];
  299. [self startGraph];
  300. CheckError(NewMusicPlayer(&_musicPlayer), "NewMusicPlayer");
  301. CheckError(MusicPlayerSetSequence(self.musicPlayer, self.musicSequence), "MusicPlayerSetSequence");
  302. //关联Sequence和AUGraph
  303. CheckError(MusicSequenceSetAUGraph(self.musicSequence, self.processingGraph),
  304. "MusicSequenceSetAUGraph");
  305. // 获取速度
  306. [self getTempoMessage];
  307. MusicTrack track;
  308. MusicTimeStamp maxTrackLength = 0;
  309. self.instrumentTrackNameArray = [NSMutableArray array];
  310. self.baseInstrumentArray = [NSMutableArray array];
  311. for (int i = 0; i < self.trackCount; i++) {
  312. CheckError(MusicSequenceGetIndTrack (self.musicSequence, i, &track), "MusicSequenceGetIndTrack");
  313. MusicTimeStamp track_length;
  314. UInt32 tracklength_size = sizeof(MusicTimeStamp);
  315. CheckError(MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &track_length, &tracklength_size), "kSequenceTrackProperty_TrackLength");
  316. MusicTimeStamp track_offset = 0;
  317. UInt32 trackoffset_size = sizeof(track_offset);
  318. CheckError(MusicTrackGetProperty(track, kSequenceTrackProperty_OffsetTime, &track_offset, &trackoffset_size), "kSequenceTrackProperty_OffsetTime_TrackOffset");
  319. MusicTimeStamp trackLength = track_length + track_offset;
  320. if(trackLength>maxTrackLength) maxTrackLength = trackLength;
  321. MusicTrackLoopInfo loopInfo;
  322. UInt32 lisize = sizeof(MusicTrackLoopInfo);
  323. CheckError(MusicTrackGetProperty(track,kSequenceTrackProperty_LoopInfo, &loopInfo, &lisize ), "kSequenceTrackProperty_LoopInfo");
  324. NSLog(@"Loop info: duration %f", loopInfo.loopDuration);
  325. [self iterate:track TrackIndex:i];
  326. CheckError(MusicTrackSetDestNode(track, [self.samplerNodeList[i] intValue]), "MusicTrackSetDestNode");
  327. }
  328. self.trackLength = maxTrackLength;
  329. // 获取总时长
  330. CheckError(MusicSequenceGetSecondsForBeats(self.musicSequence, maxTrackLength, &_totalTime), "MusicSequenceGetSecondsForBeats");
  331. NSLog(@"Music total time is: %f",self.totalTime);
  332. __weak typeof(self) weakSelf=self;
  333. dispatch_async(dispatch_get_main_queue(), ^{
  334. if([weakSelf.delegate respondsToSelector:@selector(GetMusicTotalTime:)]){
  335. [weakSelf.delegate GetMusicTotalTime:weakSelf.totalTime];
  336. }
  337. });
  338. /*
  339. 播放准备
  340. */
  341. self.currentTime = 0;
  342. // 初始化成功回调
  343. dispatch_async(dispatch_get_main_queue(), ^{
  344. if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(initPlayerEngineSuccess:)]) {
  345. [weakSelf.delegate initPlayerEngineSuccess:weakSelf.totalTime];
  346. }
  347. });
  348. return YES;
  349. }
  350. else {
  351. NSLog(@"文件不存在 !!!");
  352. return NO;
  353. }
  354. }
  355. - (void)getTempoMessage {
  356. OSStatus result = noErr;
  357. MusicTrack tempoTrack;
  358. result = MusicSequenceGetTempoTrack(self.musicSequence, &tempoTrack);
  359. if (noErr != result) { // 未获取到tempo轨道
  360. NSLog(@"MusicSequenceGetTempoTrack, %d", (int)result);
  361. return;
  362. }
  363. MusicEventIterator iterator;
  364. CheckError(NewMusicEventIterator(tempoTrack, &iterator), "NewMusicEventIterator");
  365. MusicEventType eventType;
  366. MusicTimeStamp eventTimeStamp;
  367. UInt32 eventDataSize;
  368. const void *eventData;
  369. Boolean hasCurrentEvent = NO;
  370. CheckError(MusicEventIteratorHasCurrentEvent(iterator, &hasCurrentEvent), "MusicEventIteratorHasCurrentEvent");
  371. while (hasCurrentEvent) {
  372. MusicEventIteratorGetEventInfo(iterator, &eventTimeStamp, &eventType, &eventData, &eventDataSize);
  373. switch (eventType) {
  374. case kMusicEventType_ExtendedTempo: // 速度
  375. {
  376. ExtendedTempoEvent *ext_tempo_evt = (ExtendedTempoEvent*)eventData;
  377. NSLog(@"ExtendedTempoEvent, bpm %f", ext_tempo_evt->bpm);
  378. self.baseRate = ext_tempo_evt->bpm;
  379. }
  380. break;
  381. default:
  382. break;
  383. }
  384. CheckError(MusicEventIteratorHasNextEvent(iterator, &hasCurrentEvent), "MusicEventIteratorHasCurrentEvent");
  385. CheckError(MusicEventIteratorNextEvent(iterator), "MusicEventIteratorNextEvent");
  386. }
  387. }
  388. // 读取track 的event信息
  389. - (void)iterate:(MusicTrack)track TrackIndex:(int)index {
  390. MusicEventIterator iterator;
  391. CheckError(NewMusicEventIterator(track, &iterator), "NewMusicEventIterator");
  392. MusicEventType eventType;
  393. MusicTimeStamp eventTimeStamp;
  394. UInt32 eventDataSize;
  395. const void *eventData;
  396. Boolean hasCurrentEvent = NO;
  397. CheckError(MusicEventIteratorHasCurrentEvent(iterator, &hasCurrentEvent), "MusicEventIteratorHasCurrentEvent");
  398. while (hasCurrentEvent)
  399. {
  400. MusicEventIteratorGetEventInfo(iterator, &eventTimeStamp, &eventType, &eventData, &eventDataSize);
  401. // NSLog(@"event timeStamp %f ", eventTimeStamp);
  402. switch (eventType) {
  403. case kMusicEventType_ExtendedNote : {
  404. }
  405. break;
  406. case kMusicEventType_ExtendedTempo : { // 速度
  407. // ExtendedTempoEvent* ext_tempo_evt = (ExtendedTempoEvent*)eventData;
  408. // NSLog(@"ExtendedTempoEvent, bpm %f", ext_tempo_evt->bpm);
  409. // self.baseRate = ext_tempo_evt->bpm;
  410. }
  411. break;
  412. case kMusicEventType_User : {
  413. // MusicEventUserData* user_evt = (MusicEventUserData*)eventData;
  414. // NSLog(@"MusicEventUserData, data length %u", (unsigned int)user_evt->length);
  415. }
  416. break;
  417. case kMusicEventType_Meta : {
  418. MIDIMetaEvent* meta_evt = (MIDIMetaEvent*)eventData;
  419. // NSLog(@"MIDIMetaEvent, event type %d", meta_evt->metaEventType);
  420. if (meta_evt->metaEventType == 0x03) { // 音序或 track 的名称
  421. NSString *name = [[NSString alloc] initWithBytes:meta_evt->data length:meta_evt->dataLength encoding:NSUTF8StringEncoding];
  422. name = [[name componentsSeparatedByString:@","] lastObject];
  423. name = [name replaceAll:@"\0" WithString:@""];
  424. // NSLog(@"------- name -----%@",name);
  425. [self.instrumentTrackNameArray addObject:name];
  426. }
  427. }
  428. break;
  429. case kMusicEventType_MIDINoteMessage : { // 音符信息
  430. // MIDINoteMessage* note_evt = (MIDINoteMessage*)eventData;
  431. // NSLog(@"note event channel %d", note_evt->channel);
  432. // NSLog(@"note event note %d", note_evt->note);
  433. // NSLog(@"note event duration %f", note_evt->duration);
  434. // NSLog(@"note event velocity %d", note_evt->velocity);
  435. }
  436. break;
  437. case kMusicEventType_MIDIChannelMessage : { // channel message
  438. MIDIChannelMessage* channel_evt = (MIDIChannelMessage*)eventData;
  439. if((channel_evt->status& 0xF0) == 0xC0 ) {
  440. // CHANNEL_PROGRAM_CHANGE 获取instrument id
  441. // NSLog(@"-- track index %d ------ instrument %d ", index, channel_evt->data1);
  442. if (channel_evt->data1 == self.instrumentId) {
  443. self.baseInstrumentTrack = index;
  444. [self.baseInstrumentArray addObject:@(index)];
  445. }
  446. // /*
  447. // 静音处理
  448. // */
  449. // Boolean isSet = NO; /* 判断轨道是否设置静音 */
  450. // if (self.isMute){
  451. //
  452. // for (int i = 0; i < self.instrumentArray.count; i++){
  453. // int instrument = [self.instrumentArray[i] intValue];
  454. // if(channel_evt->data1 == instrument){
  455. // isSet = YES;
  456. // CheckError(MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &_isMute, sizeof(_isMute)), "SetMusicTrackMute");
  457. // }
  458. // }
  459. //
  460. // }
  461. // if (self.muteDrum && ((channel_evt->status& 0x0F) == 9)){
  462. // isSet = YES;
  463. // CheckError(MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &_muteDrum, sizeof(_muteDrum)), "SetMusicTrackMuteDrum");
  464. // }
  465. }
  466. else if ((channel_evt->status& 0xF0) == 0xB7) { // 音量控制
  467. // NSLog(@"channel event status %X", channel_evt->status);
  468. // NSLog(@"channel event d1 %X", channel_evt->data1);
  469. // NSLog(@"channel event d2 %X", channel_evt->data2);
  470. }
  471. else {
  472. // NSLog(@"channel event status %X", channel_evt->status);
  473. // NSLog(@"channel event d1 %X", channel_evt->data1);
  474. // NSLog(@"channel event d2 %X", channel_evt->data2);
  475. }
  476. }
  477. break ;
  478. case kMusicEventType_MIDIRawData : {
  479. // MIDIRawData* raw_data_evt = (MIDIRawData*)eventData;
  480. // NSLog(@"MIDIRawData, length %lu", raw_data_evt->length);
  481. }
  482. break ;
  483. case kMusicEventType_Parameter : {
  484. // ParameterEvent* parameter_evt = (ParameterEvent*)eventData;
  485. // NSLog(@"ParameterEvent, parameterid %lu", parameter_evt->parameterID);
  486. }
  487. break ;
  488. default :
  489. break ;
  490. }
  491. CheckError(MusicEventIteratorHasNextEvent(iterator, &hasCurrentEvent), "MusicEventIteratorHasCurrentEvent");
  492. CheckError(MusicEventIteratorNextEvent(iterator), "MusicEventIteratorNextEvent");
  493. }
  494. }
  495. /* 根据轨道名称获取单个轨道的编号*/
  496. - (NSInteger)getSingleTrackNumByName:(NSString *)trackName {
  497. NSLog(@"track name ----%@",self.instrumentTrackNameArray);
  498. for (NSInteger i = 0; i < self.instrumentTrackNameArray.count; i++) {
  499. NSString *instrumentTrackName = self.instrumentTrackNameArray[i];
  500. if ([trackName isEqualToString:instrumentTrackName]) {
  501. return i;
  502. }
  503. }
  504. return -1;
  505. }
  506. /* 通过轨道名称获取对应的轨道*/
  507. - (NSMutableArray *)getTrackNumerFromName:(NSArray *)trackNameArray {
  508. NSMutableArray *trackArray = [NSMutableArray array];
  509. NSLog(@"track name ----%@",self.instrumentTrackNameArray);
  510. for (NSString *name in trackNameArray) {
  511. for (NSInteger i = 0; i < self.instrumentTrackNameArray.count; i++) {
  512. NSString *instrumentTrackName = self.instrumentTrackNameArray[i];
  513. // 包含name就添加对应的轨道
  514. if ([name isEqualToString:instrumentTrackName]) {
  515. [trackArray addObject:@(i)];
  516. }
  517. }
  518. }
  519. return trackArray;
  520. }
  521. - (void)muteTrackWithTrackNameExclude:(NSMutableArray *)trackNameArray {
  522. NSMutableArray *unMuteArray = [self getTrackNumerFromName:trackNameArray];
  523. for (UInt32 i = 0; i < self.trackCount; i++) {
  524. Boolean mutedBoolean = true;
  525. MusicTrack track;
  526. MusicSequenceGetIndTrack(self.musicSequence, i, &track);
  527. MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mutedBoolean, sizeof(mutedBoolean));
  528. }
  529. Boolean mutedBoolean = FALSE;
  530. for (NSNumber *trackNo in unMuteArray) {
  531. MusicTrack track;
  532. MusicSequenceGetIndTrack(self.musicSequence, trackNo.intValue, &track);
  533. MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mutedBoolean, sizeof(mutedBoolean));
  534. }
  535. }
  536. // 播放mid文件
  537. - (void)playMIDIFile {
  538. CheckError(MusicPlayerPreroll(self.musicPlayer), "MusicPlayerPreroll");
  539. CheckError(MusicPlayerSetPlayRateScalar(self.musicPlayer, self.timeRatio), "MusicPlayerSetPlayRateScalar");
  540. CheckError(MusicPlayerStart(self.musicPlayer), "MusicPlayerStart");
  541. self.playing = YES;
  542. __weak typeof(self) weakSelf = self;
  543. dispatch_queue_t queue = dispatch_queue_create("Timer", DISPATCH_QUEUE_SERIAL);
  544. // 定时器回调
  545. [[GCDTimer shared] scheduleGCDTimerWithName:@"MusicPlayerTimer" Interval:self.reportTime Queue:queue Repeats:YES Action:^{
  546. MusicTimeStamp currentStamp;
  547. CheckError(MusicPlayerGetTime(weakSelf.musicPlayer, &currentStamp), "MusicPlayerGetTime_CurrentTimeStamp");
  548. double currentPlayTime;
  549. CheckError(MusicSequenceGetSecondsForBeats(weakSelf.musicSequence, currentStamp, &currentPlayTime), "MusicSequencself->GetSecondsForBeats_CurrentTime");
  550. weakSelf.currentTime = currentPlayTime;
  551. if (weakSelf.currentTime >= weakSelf.totalTime) {
  552. weakSelf.currentTime = weakSelf.totalTime;
  553. dispatch_async(dispatch_get_main_queue(), ^{
  554. if ([weakSelf.delegate respondsToSelector:@selector(playEnd)]) {
  555. [weakSelf.delegate playEnd];
  556. }
  557. // 进度上报100%
  558. if([weakSelf.delegate respondsToSelector:@selector(ProgressUpdated:currentTime:)]) {
  559. [weakSelf.delegate ProgressUpdated:weakSelf.currentTime/weakSelf.totalTime currentTime:weakSelf.currentTime];
  560. }
  561. });
  562. [[GCDTimer shared] cancelAllTimer];
  563. CheckError(MusicPlayerStop(weakSelf.musicPlayer), "MusicPlayerStop");
  564. weakSelf.playing = NO;
  565. weakSelf.currentTime = 0;
  566. CheckError(MusicSequenceGetBeatsForSeconds(weakSelf.musicSequence, weakSelf.currentTime, &currentStamp), "MusicSequenceGetBeatsForSeconds_SetCurrentStamp");
  567. CheckError(MusicPlayerSetTime(weakSelf.musicPlayer, currentStamp), "MusicPlayerSetTime_SetZero");
  568. }
  569. else {
  570. // 如果是选段播放 到结束
  571. if (weakSelf.endTime != 0 && weakSelf.currentTime >= weakSelf.endTime) {
  572. dispatch_async(dispatch_get_main_queue(), ^{
  573. if ([weakSelf.delegate respondsToSelector:@selector(playEnd)]) {
  574. [weakSelf.delegate playEnd];
  575. }
  576. });
  577. [[GCDTimer shared] cancelAllTimer];
  578. CheckError(MusicPlayerStop(weakSelf.musicPlayer), "MusicPlayerStop");
  579. weakSelf.playing = NO;
  580. weakSelf.currentTime = 0;
  581. CheckError(MusicSequenceGetBeatsForSeconds(weakSelf.musicSequence, weakSelf.currentTime, &currentStamp), "MusicSequenceGetBeatsForSeconds_SetCurrentStamp");
  582. CheckError(MusicPlayerSetTime(weakSelf.musicPlayer, currentStamp), "MusicPlayerSetTime_SetZero");
  583. }
  584. else {
  585. dispatch_async(dispatch_get_main_queue(), ^{
  586. if ([weakSelf.delegate respondsToSelector:@selector(ProgressUpdated:currentTime:)]){
  587. [weakSelf.delegate ProgressUpdated:weakSelf.currentTime/weakSelf.totalTime currentTime:weakSelf.currentTime];
  588. }
  589. });
  590. }
  591. }
  592. }];
  593. }
  594. - (void)stopPlayingMIDIFile {
  595. CheckError(MusicPlayerStop(self.musicPlayer), "MusicPlayerStop");
  596. self.playing = NO;
  597. [[GCDTimer shared] cancelAllTimer];
  598. }
  599. - (BOOL)setMusicPlayerSpeed:(double)speed {
  600. if(speed<0) return NO;
  601. else {
  602. self.timeRatio = speed;
  603. if (self.musicPlayer){
  604. CheckError(MusicPlayerSetPlayRateScalar(self.musicPlayer, self.timeRatio), "MusicPlayerSetPlayRateScalar");
  605. }
  606. return YES;
  607. }
  608. }
  609. - (void)setProgress:(double)progress {
  610. if(progress>1||progress<0) return;
  611. self.currentTime = self.totalTime * progress;
  612. MusicTimeStamp currentStamp;
  613. CheckError(MusicSequenceGetBeatsForSeconds(self.musicSequence, self.currentTime, &currentStamp), "MusicSequenceGetBeatsForSeconds_SetCurrentStamp");
  614. CheckError(MusicPlayerSetTime(self.musicPlayer, currentStamp), "MusicPlayerSetTime_SetZero");
  615. // if (self.playing) {
  616. // [self stopPlayingMIDIFile];
  617. // [self playMIDIFile];
  618. // }
  619. // else {
  620. // [self stopPlayingMIDIFile];
  621. // }
  622. }
  623. - (void)setProgressTime:(MusicTimeStamp)startTime {
  624. if (startTime < 0 || startTime > self.totalTime) {
  625. return;
  626. }
  627. self.currentTime = startTime;
  628. MusicTimeStamp currentStamp;
  629. CheckError(MusicSequenceGetBeatsForSeconds(self.musicSequence, self.currentTime, &currentStamp), "MusicSequenceGetBeatsForSeconds_SetCurrentStamp");
  630. CheckError(MusicPlayerSetTime(self.musicPlayer, currentStamp), "MusicPlayerSetTime_SetZero");
  631. // if (self.playing) {
  632. // [self stopPlayingMIDIFile];
  633. // [self playMIDIFile];
  634. // }
  635. // else {
  636. // [self stopPlayingMIDIFile];
  637. // }
  638. }
  639. - (void)muteWithInstrument:(UInt8)instrument {
  640. if(instrument<0||instrument>127) return;
  641. NSNumber* numIns = [NSNumber numberWithInt:instrument];
  642. [self.instrumentArray addObject:numIns];
  643. self.isMute = YES;
  644. }
  645. -(void)muteWithDrum {
  646. self.muteDrum = YES;
  647. }
  648. -(BOOL)isPlayingFile {
  649. return self.playing;
  650. }
  651. -(double)musicTotalTime {
  652. return self.totalTime;
  653. }
  654. -(double)musicCurrentTime {
  655. return self.currentTime;
  656. }
  657. - (void)volume:(float)volume WithTrack:(UInt32)trackNum {
  658. if(volume<0||volume>1) return;
  659. if(trackNum<0||trackNum>self.trackCount) return;
  660. CheckError(AudioUnitSetParameter(_mixerUnit,
  661. kMultiChannelMixerParam_Volume,
  662. kAudioUnitScope_Input,
  663. trackNum,
  664. volume,
  665. 0),
  666. "AudioUnitSetMixerInputVolume");
  667. }
  668. /* 调整除了 trackNum 之外的 其他轨道的音量 范围[0,1]*/
  669. - (void)volumeOtherTrackExcept:(UInt32)trackNum withVolume:(float)volume {
  670. if(volume<0||volume>1) return;
  671. if(trackNum<0||trackNum>self.trackCount) return;
  672. CheckError(AudioUnitSetParameter(_mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, trackNum, 1, 0), "AudioUnitSetMixerInputVolume");
  673. }
  674. - (void)getAllTrackVolume {
  675. for (int i = 0; i < self.trackCount; i++) {
  676. float volume = 0.0f;
  677. AudioUnitGetParameter(_mixerUnit, kMultiChannelMixerParam_Volume, kAudioUnitScope_Input, i, &volume);
  678. NSLog(@"------ track %d --- volume :%.2f", i, volume);
  679. }
  680. }
  681. - (void)muteTrack:(BOOL)isMute WithTrack:(NSMutableArray *)trackArray {
  682. Boolean mutedBoolean = isMute ? TRUE : FALSE;
  683. for (NSNumber *trackNo in trackArray) {
  684. MusicTrack track;
  685. MusicSequenceGetIndTrack(self.musicSequence, trackNo.intValue, &track);
  686. MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mutedBoolean, sizeof(mutedBoolean));
  687. }
  688. }
  689. - (void)cleanup {
  690. if (self.musicPlayer) {
  691. //当前在播放,先暂停
  692. if ([self isPlayingFile]) {
  693. [self stopPlayingMIDIFile];
  694. }
  695. CheckError(MusicSequenceGetTrackCount(self.musicSequence, &_trackCount), "MusicSequenceGetTrackCount");
  696. MusicTrack track;
  697. for (int i = 0;i < self.trackCount; i++) {
  698. CheckError(MusicSequenceGetIndTrack (self.musicSequence,0,&track), "MusicSequenceGetIndTrack");
  699. CheckError(MusicSequenceDisposeTrack(self.musicSequence, track), "MusicSequenceDisposeTrack");
  700. }
  701. CheckError(DisposeMusicPlayer(self.musicPlayer), "DisposeMusicPlayer");
  702. CheckError(DisposeMusicSequence(self.musicSequence), "DisposeMusicSequence");
  703. CheckError(DisposeAUGraph(self.processingGraph), "DisposeAUGraph");
  704. self.playing=NO;
  705. [self.samplerNodeList removeAllObjects];
  706. [self.samplerUnitList removeAllObjects];
  707. [self.instrumentArray removeAllObjects];
  708. [self.instrumentTrackNameArray removeAllObjects];
  709. self.isMute = NO;
  710. self.muteDrum = NO;
  711. NSLog(@"CleanUp!");
  712. }
  713. }
  714. #pragma mark ------ 变调 调整hz
  715. - (void)transformTo442Hz {
  716. [self adjustPitchByHZ:442.0f];
  717. }
  718. // hz调整 440 - 442。。。。。。。
  719. - (void)adjustPitchByHZ:(float)newHZ {
  720. // 415 ~ 466
  721. if (newHZ < 415 || newHZ > 466) {
  722. return;
  723. }
  724. /**
  725. 1200音分等于一个八度音程,频率比为2:1,等程半音(相当于相邻钢琴键间的音程)等于100音分。这意味着1音分正好等于21/1200,即
  726. 如果知道两个音a和b的频率,两个音相距的音分值n可用下列公式计算(类似分贝定义式的形式,目的是为了使指数形式的物理单位线性化,使其化为对数):
  727. n=1200 *log2(a/b) == 3986 *log10(a/b)
  728. */
  729. Float32 censt = log2(newHZ/440.0) * 1200;
  730. AudioUnitSetParameter(self.pitchUnit, kNewTimePitchParam_Pitch, kAudioUnitScope_Global, 0, censt, 0);
  731. }
  732. #pragma mark ---- 自动循环功能和播放时同步节拍器暂未实现
  733. - (void)startPlaybackLoop {
  734. self.isLooping = YES;
  735. [self startPlaybackFromPosition:0];
  736. }
  737. - (void)startPlaybackFromPosition:(MusicTimeStamp)position {
  738. if (self.playing) {
  739. [self stopPlayback];
  740. }
  741. [self loopTrackWhenNeed];
  742. [self addClickTrackWhenNeededFromTimeStamp:position];
  743. // CheckError(<#OSStatus error#>, <#const char *operation#>)
  744. }
  745. #pragma mark ---- Looping
  746. - (void)loopTrackWhenNeed {
  747. if (self.isLooping) {
  748. MusicTrackLoopInfo loopInfo;
  749. loopInfo.numberOfLoops = 0;
  750. loopInfo.loopDuration = self.trackLength;
  751. MusicTrack track;
  752. // 设置循环播放属性
  753. for (int i = 0; i < self.trackCount; i++) {
  754. CheckError(MusicSequenceGetIndTrack (self.musicSequence, i, &track), "MusicSequenceGetIndTrack");
  755. CheckError(MusicTrackSetProperty(track, kSequenceTrackProperty_LoopInfo, &loopInfo, sizeof(loopInfo)), "MusicTrackSetProperty loop");
  756. }
  757. }
  758. }
  759. #pragma mark ----- click tracks
  760. - (void)addClickTrackWhenNeededFromTimeStamp:(MusicTimeStamp)fromTimeStamp {
  761. if (self.isClickPlayer) {
  762. return;
  763. }
  764. if (self.isClickTrackEnabled == NO) {
  765. return;
  766. }
  767. self.clickPlayer = [[MidiPlayerEngine alloc] init];
  768. self.clickPlayer->_isClickPlayer = YES;
  769. // 添加节拍器mid声轨
  770. }
  771. #pragma mark --- Properties
  772. - (void)setIsLooping:(BOOL)isLooping {
  773. if (isLooping != _isLooping) {
  774. _isLooping = isLooping;
  775. if (self.playing) { // 如果正在播放 停止之后从新开启播放
  776. }
  777. }
  778. }
  779. #pragma mark --- Lazyload
  780. - (NSMutableArray*)samplerNodeList {
  781. if (!_samplerNodeList) {
  782. _samplerNodeList = [[NSMutableArray alloc] init];
  783. }
  784. return _samplerNodeList;
  785. }
  786. - (NSMutableArray*)samplerUnitList {
  787. if (!_samplerUnitList) {
  788. _samplerUnitList = [[NSMutableArray alloc] init];
  789. }
  790. return _samplerUnitList;
  791. }
  792. -(NSMutableArray*)instrumentArray {
  793. if (!_instrumentArray) {
  794. _instrumentArray = [[NSMutableArray alloc] init];
  795. }
  796. return _instrumentArray;
  797. }
  798. - (NSMutableArray *)muteTrackArray {
  799. if (!_muteTrackArray) {
  800. _muteTrackArray = [NSMutableArray array];
  801. }
  802. return _muteTrackArray;
  803. }
  804. - (void)dealloc {
  805. NSLog(@"************ player engine dealloc!");
  806. }
  807. /*
  808. 物理连接
  809. ____________
  810. | |
  811. | Sampler |-------
  812. | | |
  813. ------------ |
  814. |
  815. ____________ | ---------------------- ------------
  816. | | ----->| | | |
  817. | Sampler |------------->| MultiChannel Mixer |------------->| I/O |
  818. | | ----->| | | |
  819. ------------ | ---------------------- ------------
  820. |
  821. ____________ |
  822. | | |
  823. | Sampler |-------
  824. | |
  825. ------------
  826. --------------------- -------------------------------------------------
  827. | MusicSequence | | AUGraph |
  828. | | | |
  829. | MusicTrack1 ---|--------| ->MIDISynth1 |
  830. | | | --->MixerNode -------> OutputNode|
  831. | MusicTrack2 ---|--------| ->MIDISynth2 |
  832. | | | |
  833. --------------------- -------------------------------------------------
  834. */
  835. @end