Created
August 24, 2015 20:56
-
-
Save starakaj/cc1a68c9b13c08d98dd4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.m | |
// SimpleAudioTest | |
// | |
// Created by Sam Tarakajian on 8/24/15. | |
// Copyright © 2015 Sam Tarakajian. All rights reserved. | |
// | |
#import "ViewController.h" | |
@import AudioToolbox; | |
enum { | |
kMIDIMessage_NoteOn = 0x9, | |
kMIDIMessage_NoteOff = 0x8, | |
}; | |
@interface ViewController () { | |
AUGraph _audioUnitGraph; | |
MusicTrack _rawMusicTrack; | |
AUNode _remoteAUNode; | |
AUNode _mixerAUNode; | |
AUNode _samplerAUNode; | |
MusicPlayer _player; | |
MusicSequence _sequence; | |
MusicTrack _track; | |
MIDIClientRef _client; | |
MIDIEndpointRef _endpoint; | |
} | |
@property (nonatomic, strong) NSTimer *pollStateTimer; | |
- (void)createAudioGraph; | |
- (void)createRemoteAUNode; | |
- (void)createMixerAUNode; | |
- (void)createSamplerAUNode; | |
- (void)pollState; | |
- (void)setMusicTrackLength:(MusicTrack *)track length:(MusicTimeStamp)length; | |
- (void)setMusicTrackLoopDuration:(MusicTrack *)track loopDuration:(MusicTimeStamp)loopDuration; | |
@end | |
@implementation ViewController | |
- (void)createAudioGraph | |
{ | |
__unused OSStatus status = NewAUGraph(&_audioUnitGraph); | |
NSAssert(status == noErr, @"Assert: NewAUGraph failed: %d", (int)status); | |
} | |
- (void)createRemoteAUNode | |
{ | |
AudioComponentDescription description; | |
description.componentType = kAudioUnitType_Output; | |
description.componentSubType = kAudioUnitSubType_RemoteIO; | |
description.componentManufacturer = kAudioUnitManufacturer_Apple; | |
description.componentFlags = 0; | |
description.componentFlagsMask = 0; | |
AUGraphAddNode(_audioUnitGraph, &description, &_remoteAUNode); | |
} | |
- (void)createMixerAUNode | |
{ | |
AudioComponentDescription description; | |
description.componentType = kAudioUnitType_Mixer; | |
description.componentSubType = kAudioUnitSubType_MultiChannelMixer; | |
description.componentManufacturer = kAudioUnitManufacturer_Apple; | |
description.componentFlags = 0; | |
description.componentFlagsMask = 0; | |
AUGraphAddNode(_audioUnitGraph, &description, &_mixerAUNode); | |
} | |
- (void)createSamplerAUNode | |
{ | |
AudioComponentDescription description; | |
description.componentType = kAudioUnitType_MusicDevice; | |
description.componentSubType = kAudioUnitSubType_Sampler; | |
description.componentManufacturer = kAudioUnitManufacturer_Apple; | |
description.componentFlags = 0; | |
description.componentFlagsMask = 0; | |
AUGraphAddNode(_audioUnitGraph, &description, &_samplerAUNode); | |
} | |
- (void)setMusicTrackLength:(MusicTrack *)t length:(MusicTimeStamp)length | |
{ | |
MusicTimeStamp trackLength = length; | |
__unused OSStatus status = MusicTrackSetProperty(*t, kSequenceTrackProperty_TrackLength, &trackLength, sizeof(trackLength)); | |
NSAssert(status == noErr, @"Assert: MusicTrackSetProperty failed: %d", (int)status); | |
} | |
- (void)setMusicTrackLoopDuration:(MusicTrack *)t loopDuration:(MusicTimeStamp)loopDuration | |
{ | |
// Setting numberOfLoops to 0.0 will make the track loop forrreevvverrrr | |
MusicTrackLoopInfo loopInfo; | |
loopInfo.loopDuration = loopDuration; | |
loopInfo.numberOfLoops = 0.0; | |
__unused OSStatus status = MusicTrackSetProperty(*t, kSequenceTrackProperty_LoopInfo, &loopInfo, sizeof(loopInfo)); | |
NSAssert(status == noErr, @"Assert: MusicTrackSetProperty failed: %d", (int)status); | |
} | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
__unused OSStatus status; | |
// Setup audio graph | |
[self createAudioGraph]; | |
[self createRemoteAUNode]; | |
[self createSamplerAUNode]; | |
AUGraphOpen(_audioUnitGraph); | |
AUGraphConnectNodeInput(_audioUnitGraph, _samplerAUNode, 0, _remoteAUNode, 0); | |
// Create the MusicPlayer | |
status = NewMusicPlayer(&_player); | |
status = MusicPlayerSetTime(_player, 0.0); | |
// Create the MusicSequence | |
status = NewMusicSequence(&_sequence); | |
MusicPlayerSetSequence(_player, _sequence); | |
// Add a track | |
status = MusicSequenceNewTrack(_sequence, &_track); | |
NSAssert(status == noErr, @"Assert: MusicSequenceNewTrack failed: %d", (int)status); | |
// Add a single note | |
MIDINoteMessage message; | |
message.note = 60; | |
message.velocity = 127; | |
message.releaseVelocity = 127; | |
message.duration = 0.5; | |
message.channel = 0; | |
MusicTrackNewMIDINoteEvent(_track, 1.0, &message); | |
MusicTrackNewMIDINoteEvent(_track, 2.0, &message); | |
MusicTrackNewMIDINoteEvent(_track, 3.0, &message); | |
// Setup Looping | |
[self setMusicTrackLoopDuration:&_track loopDuration:4.0]; | |
[self setMusicTrackLength:&_track length:4.0]; | |
// Attach it to the AUGraph | |
MusicSequenceSetAUGraph(_sequence, _audioUnitGraph); | |
// Start Everything | |
AUGraphStart(_audioUnitGraph); | |
MusicPlayerPreroll(_player); | |
MusicPlayerStart(_player); | |
// Start polling for status | |
self.pollStateTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(pollState) userInfo:nil repeats:YES]; | |
} | |
- (void)didReceiveMemoryWarning { | |
[super didReceiveMemoryWarning]; | |
// Dispose of any resources that can be recreated. | |
} | |
- (void)pollState | |
{ | |
MusicTimeStamp ts = 0.0; | |
__unused OSStatus status = MusicPlayerGetTime(_player, &ts); | |
NSLog(@"Progress: %f", ts); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment