root/lang/cplusplus/dokodemo_yubipiano/main.cpp @ 9513

Revision 8316, 8.1 kB (checked in by mootoh, 5 years ago)

lang/cplusplus/dokodemo_yubipiano: hacked DokodemoYubiPiano? to make it MIDI keyboard.

Line 
1/*  Copyright � 2007 Apple Inc. All Rights Reserved.
2
3  Disclaimer: IMPORTANT:  This Apple software is supplied to you by
4  Apple Inc. ("Apple") in consideration of your agreement to the
5  following terms, and your use, installation, modification or
6  redistribution of this Apple software constitutes acceptance of these
7  terms.  If you do not agree with these terms, please do not use,
8  install, modify or redistribute this Apple software.
9
10  In consideration of your agreement to abide by the following terms, and
11  subject to these terms, Apple grants you a personal, non-exclusive
12  license, under Apple's copyrights in this original Apple software (the
13  "Apple Software"), to use, reproduce, modify and redistribute the Apple
14  Software, with or without modifications, in source and/or binary forms;
15  provided that if you redistribute the Apple Software in its entirety and
16  without modifications, you must retain this notice and the following
17  text and disclaimers in all such redistributions of the Apple Software.
18  Neither the name, trademarks, service marks or logos of Apple Inc.
19  may be used to endorse or promote products derived from the Apple
20  Software without specific prior written permission from Apple.  Except
21  as expressly stated in this notice, no other rights or licenses, express
22  or implied, are granted by Apple herein, including but not limited to
23  any patent rights that may be infringed by your derivative works or by
24  other works in which the Apple Software may be incorporated.
25
26  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
27  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
28  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
29  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
30  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
31
32  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
33  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
36  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
37  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
38  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
39  POSSIBILITY OF SUCH DAMAGE.
40*/
41
42// This is a simple test case of making an simple graph with a DLSSynth, Limiter and Ouput unit
43// we're going to use a graph because its easier for it to just handle the setup and connections, etc...
44
45#include <CoreServices/CoreServices.h> //for file stuff
46#include <AudioUnit/AudioUnit.h>
47#include <AudioToolbox/AudioToolbox.h> //for AUGraph
48#include <unistd.h> // used for usleep...
49#include <sys/time.h>
50#include <iostream>
51#include <vector>
52#include <gainer.h>
53#include "filter.h"
54
55// This call creates the Graph and the Synth unit...
56OSStatus  CreateAUGraph (AUGraph &outGraph, AudioUnit &outSynth)
57{
58  OSStatus result;
59  //create the nodes of the graph
60  AUNode synthNode, limiterNode, outNode;
61
62  ComponentDescription cd;
63  cd.componentManufacturer = kAudioUnitManufacturer_Apple;
64  cd.componentFlags = 0;
65  cd.componentFlagsMask = 0;
66
67  require_noerr (result = NewAUGraph (&outGraph), home);
68
69  cd.componentType = kAudioUnitType_MusicDevice;
70  cd.componentSubType = kAudioUnitSubType_DLSSynth;
71
72  require_noerr (result = AUGraphAddNode (outGraph, &cd, &synthNode), home);
73
74  cd.componentType = kAudioUnitType_Effect;
75  cd.componentSubType = kAudioUnitSubType_PeakLimiter; 
76
77  require_noerr (result = AUGraphAddNode (outGraph, &cd, &limiterNode), home);
78
79  cd.componentType = kAudioUnitType_Output;
80  cd.componentSubType = kAudioUnitSubType_DefaultOutput; 
81  require_noerr (result = AUGraphAddNode (outGraph, &cd, &outNode), home);
82
83  require_noerr (result = AUGraphOpen (outGraph), home);
84
85  require_noerr (result = AUGraphConnectNodeInput (outGraph, synthNode, 0, limiterNode, 0), home);
86  require_noerr (result = AUGraphConnectNodeInput (outGraph, limiterNode, 0, outNode, 0), home);
87
88  // ok we're good to go - get the Synth Unit...
89  require_noerr (result = AUGraphNodeInfo(outGraph, synthNode, 0, &outSynth), home);
90
91home:
92  return result;
93}
94
95// some MIDI constants:
96enum {
97  kMidiMessage_ControlChange    = 0xB,
98  kMidiMessage_ProgramChange    = 0xC,
99  kMidiMessage_BankMSBControl   = 0,
100  kMidiMessage_BankLSBControl   = 32,
101  kMidiMessage_NoteOn           = 0x9
102};
103
104const int OCTAVE[2] = {64, 74};
105const int OCTAVE_INTERVAL(1);
106const int FINGERS[4] = {0, 2, 4, 5};
107const int OCTAVE_RANGE(7);
108
109int main (int argc, const char * argv[]) {
110  AUGraph graph = 0;
111  AudioUnit synthUnit;
112  OSStatus result;
113  char* bankPath = 0;
114
115  UInt8 midiChannelInUse = 0; //we're using midi channel 1...
116
117  // this is the only option to main that we have...
118  // just the full path of the sample bank...
119
120  // On OS X there are known places were sample banks can be stored
121  // Library/Audio/Sounds/Banks - so you could scan this directory and give the user options
122  // about which sample bank to use...
123  if (argc > 2)
124    bankPath = const_cast<char*>(argv[2]);
125
126  Gainer gainer(argv[1]);
127  std::vector <bool> prev(gainer.digital_inputs.size(), false);
128  MovingAverageFilter filter(4);
129  int octave(0);
130  struct timeval start, stop;
131  gettimeofday(&start, NULL);
132
133  gainer.continuous_digital_inputs();
134  gainer.continuous_analog_inputs();
135
136  require_noerr (result = CreateAUGraph (graph, synthUnit), home);
137
138  // if the user supplies a sound bank, we'll set that before we initialize and start playing
139  if (bankPath)
140  {
141    FSRef fsRef;
142    require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &fsRef, 0), home);
143
144    printf ("Setting Sound Bank:%s\n", bankPath);
145
146    require_noerr (result = AudioUnitSetProperty (synthUnit,
147          kMusicDeviceProperty_SoundBankFSRef,
148          kAudioUnitScope_Global, 0,
149          &fsRef, sizeof(fsRef)), home);
150
151  }
152
153  // ok we're set up to go - initialize and start the graph
154  require_noerr (result = AUGraphInitialize (graph), home);
155
156  //set our bank
157  require_noerr (result = MusicDeviceMIDIEvent(synthUnit,
158        kMidiMessage_ControlChange << 4 | midiChannelInUse,
159        kMidiMessage_BankMSBControl, 0,
160        0/*sample offset*/), home);
161
162  require_noerr (result = MusicDeviceMIDIEvent(synthUnit,
163        kMidiMessage_ProgramChange << 4 | midiChannelInUse,
164        0/*prog change num*/, 0,
165        0/*sample offset*/), home);
166
167  CAShow (graph); // prints out the graph so we can see what it looks like...
168
169  require_noerr (result = AUGraphStart (graph), home);
170
171  // we're going to play an octave of MIDI notes: one a second
172  while (true) {
173
174    //UInt32 noteNum = i + 60;
175
176    bool moved(false);
177    int x(filter.filter(gainer.analog_inputs[0]-126));
178    if (x < -OCTAVE[0]) {
179      std::cout << x << std::endl;
180      gettimeofday(&stop, NULL);
181      if (stop.tv_sec - start.tv_sec > OCTAVE_INTERVAL) {
182        octave++;
183        start = stop;
184      }
185      moved = true;
186    } else if (x > OCTAVE[1]) {
187      std::cout << x << std::endl;
188      gettimeofday(&stop, NULL);
189      if (stop.tv_sec - start.tv_sec > OCTAVE_INTERVAL) {
190        octave--;
191        start = stop;
192      }
193      moved = true;
194    }
195
196    for (size_t j(0); j<prev.size(); j++) {
197      //std::cout << gainer.digital_inputs[j] << std::endl;
198      if (gainer.digital_inputs[j] and not prev[j])  {
199        if (moved)
200          std::cout << prev[j] << std::endl;
201
202        UInt32 noteNum = 60 + FINGERS[j] + octave*OCTAVE_RANGE;
203        UInt32 onVelocity = 127;
204        UInt32 noteOnCommand =  kMidiMessage_NoteOn << 4 | midiChannelInUse;
205
206        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, 0, 0), home);
207        printf ("Playing Note: Status: 0x%lX, Note: %ld, Vel: %ld\n", noteOnCommand, noteNum, onVelocity);
208        require_noerr (result = MusicDeviceMIDIEvent(synthUnit, noteOnCommand, noteNum, onVelocity, 0), home);
209
210      }
211      prev[j] = gainer.digital_inputs[j];
212    }
213
214    usleep (1 * 10 * 1000);
215  }
216
217  // ok we're done now
218
219home:
220  if (graph) {
221    AUGraphStop (graph); // stop playback - AUGraphDispose will do that for us but just showing you what to do
222    DisposeAUGraph (graph);
223  }
224  return result;
225}
Note: See TracBrowser for help on using the browser.