source: roaraudio/libroardsp/midi.c @ 3003:9d0935291fca

Last change on this file since 3003:9d0935291fca was 2424:ebf8be51199e, checked in by phi, 15 years ago

got it... something simular to working at least may completly be replaced by synth

File size: 5.2 KB
Line 
1//midi.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - August 2008
5 *
6 *  This file is part of libroardsp a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroardsp is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "libroardsp.h"
26
27struct {
28 uint16_t id;
29 unsigned char midiid;
30 float freq;
31 char * name;
32} _libroar_notes[] = {
33 {ROAR_MIDI_NOTE_C , 60, 261.625565, "C" },
34 {ROAR_MIDI_NOTE_Cs, 61, 277.182631, "C#"},
35 {ROAR_MIDI_NOTE_D , 62, 293.664768, "D" },
36 {ROAR_MIDI_NOTE_Ds, 63, 311.126984, "D#"},
37 {ROAR_MIDI_NOTE_E , 64, 329.627557, "E" },
38 {ROAR_MIDI_NOTE_F , 65, 349.228231, "F" },
39 {ROAR_MIDI_NOTE_Fs, 66, 369.994423, "F#"},
40 {ROAR_MIDI_NOTE_G , 67, 391.995436, "G" },
41 {ROAR_MIDI_NOTE_Gs, 68, 415.304698, "G#"},
42 {ROAR_MIDI_NOTE_A , 69, 440.000000, "A" },
43 {ROAR_MIDI_NOTE_As, 70, 466.163762, "A#"},
44 {ROAR_MIDI_NOTE_B , 71, 493.883301, "B" },
45 {0, 0, 0, NULL}
46};
47
48char         * roar_midi_note2name   (uint16_t note) {
49 int i;
50
51 for (i = 0; _libroar_notes[i].name != NULL; i++)
52  if ( _libroar_notes[i].id == note )
53   return _libroar_notes[i].name;
54
55 return NULL;
56}
57
58uint16_t   roar_midi_name2note   (char * note) {
59 int i;
60
61 for (i = 0; _libroar_notes[i].name != NULL; i++)
62  if ( strcasecmp(_libroar_notes[i].name, note) == 0 )
63   return _libroar_notes[i].id;
64
65 return ROAR_MIDI_NOTE_NONE;
66}
67
68uint16_t       roar_midi_midi2note   (unsigned char midiid) {
69 int i;
70
71 for (i = 0; _libroar_notes[i].name != NULL; i++)
72  if ( _libroar_notes[i].midiid == midiid )
73   return _libroar_notes[i].id;
74
75 return ROAR_MIDI_NOTE_NONE;
76}
77
78float          roar_midi_note2freq   (uint16_t note) {
79 int i;
80
81 for (i = 0; _libroar_notes[i].name != NULL; i++)
82  if ( _libroar_notes[i].id == note )
83   return _libroar_notes[i].freq;
84
85 return -1;
86}
87
88int            roar_midi_note_from_midiid(struct roar_note_octave * note, unsigned char midiid) {
89 int oct;
90
91 if ( note == NULL || midiid > 127 )
92  return -1;
93
94 memset(note, 0, sizeof(struct roar_note_octave));
95
96 note->octave = ((int) midiid/12) - 5;
97 note->note   = roar_midi_midi2note((midiid % 12) + 60);
98
99 oct = 1 << abs(note->octave);
100
101 note->freq = roar_midi_note2freq(note->note);
102
103 if ( note->octave < 0 ) {
104  note->freq /= oct;
105 } else {
106  note->freq *= oct;
107 }
108
109 return 0;
110}
111
112int            roar_midi_find_octave (char * note);
113int            roar_midi_add_octave  (struct roar_note_octave * note) {
114 note->name[0] = 0;
115 return -1;
116}
117
118int            roar_midi_notefill    (struct roar_note_octave * note) {
119 int oct;
120
121 if ( !note )
122  return -1;
123
124 if ( note->note && note->name[0] == 0 ) {
125  roar_midi_add_octave(note);
126 } else if ( !note->note && note->name[0] != 0 ) {
127  return -1;
128 }
129
130 oct = 1 << abs(note->octave);
131
132 note->freq = roar_midi_note2freq(note->note);
133
134 // TODO: fix this: freq is freq*2^octave
135 if ( note->octave < 0 ) {
136  note->freq /= oct;
137 } else {
138  note->freq *= oct;
139 }
140
141 return 0;
142}
143
144int roar_midi_gen_tone (struct roar_note_octave * note, int16_t * samples, float t, int rate, int channels, int type, void * opts) {
145#ifdef ROAR_HAVE_LIBM
146 int i, c;
147 float ct;
148 float step = 1.0/rate;
149 int16_t s;
150 float (*op)(float x) = NULL;
151
152/*
153 rate: 1/s
154 t   : 1s
155 freq: 1/s
156 rew : 1s
157*/
158
159 if ( type == ROAR_MIDI_TYPE_SINE ) {
160  op = sinf;
161 } else {
162  return -1;
163 }
164
165 if ( op == NULL )
166  return -1;
167
168 ROAR_DBG("roar_midi_gen_tone(*): t=%f", t);
169
170 for (ct = 0, i = 0; ct <= t; ct += step, i += channels) {
171  s = 32767*op(2.0*M_PI*note->freq*ct);
172
173//  ROAR_DBG("roar_midi_gen_tone(*): t=%f, ct=%f, i=%i", t, ct, i);
174
175  for (c = 0; c < channels; c++)
176   samples[i+c] = s;
177 }
178
179 ROAR_DBG("roar_midi_gen_tone(*): t=%f, ct=%f, i=%i", t, ct, i);
180
181 return 0;
182#else
183 return -1;
184#endif
185}
186
187
188int roar_midi_play_note  (struct roar_stream * stream, struct roar_note_octave * note, float len) {
189 return -1;
190}
191
192int roar_midi_basic_init (struct roar_midi_basic_state * state) {
193 if (!state)
194  return -1;
195
196 state->len.mul = 1;
197 state->len.div = 60;
198
199 state->note.note   = ROAR_MIDI_NOTE_NONE;
200 state->note.octave = 0;
201
202 return 0;
203}
204
205int roar_midi_basic_play (struct roar_stream * stream, struct roar_midi_basic_state * state, char * notes) {
206 struct roar_midi_basic_state is;
207 char   cn[ROAR_MIDI_MAX_NOTENAME_LEN+1] = {0};
208 int i;
209 int have = 0;
210 struct roar_note_octave * n;
211
212 if ( !notes )
213  return -1;
214
215 if ( state == NULL ) {
216  state = &is;
217  roar_midi_basic_init(state);
218 }
219
220 n = &(state->note);
221
222 for (; *notes != 0; notes++) {
223  if ( *notes == '>' ) {
224   n->octave++;
225  } else if ( *notes == '<' ) {
226   n->octave--;
227  } else if ( *notes != ' ' ) {
228   have++;
229  }
230
231  if (have) {
232   roar_midi_play_note(stream, n, 60 * state->len.mul / state->len.div);
233   have = 0;
234  }
235 }
236
237 return 0;
238}
239
240//ll
Note: See TracBrowser for help on using the repository browser.