Skip to content

Instantly share code, notes, and snippets.

@starakaj
Created August 24, 2015 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save starakaj/cc1a68c9b13c08d98dd4 to your computer and use it in GitHub Desktop.
Save starakaj/cc1a68c9b13c08d98dd4 to your computer and use it in GitHub Desktop.
//
// 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