source: roaraudio/libroardsp/midi.c @ 1679:c68cad0eea75

Last change on this file since 1679:c68cad0eea75 was 1679:c68cad0eea75, checked in by phi, 15 years ago

freq is calced wrong

File size: 4.3 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 float freq;
30 char * name;
31} _libroar_notes[] = {
32 {ROAR_MIDI_NOTE_C , 261.625565, "C"},
33 {ROAR_MIDI_NOTE_Cs, 277.182631, "C#"},
34 {ROAR_MIDI_NOTE_D , 293.664768, "D"},
35 {ROAR_MIDI_NOTE_Ds, 311.126984, "D#"},
36 {ROAR_MIDI_NOTE_E , 329.627557, "E"},
37 {ROAR_MIDI_NOTE_F , 349.228231, "F"},
38 {ROAR_MIDI_NOTE_Fs, 369.994423, "F#"},
39 {ROAR_MIDI_NOTE_G , 391.995436, "G"},
40 {ROAR_MIDI_NOTE_Gs, 415.304698, "G#"},
41 {ROAR_MIDI_NOTE_A , 440.000000, "A"},
42 {ROAR_MIDI_NOTE_As, 466.163762, "A#"},
43 {ROAR_MIDI_NOTE_B , 493.883301, "B"},
44 {0, 0, NULL}
45};
46
47char         * roar_midi_note2name   (uint16_t note) {
48 int i;
49
50 for (i = 0; _libroar_notes[i].name != NULL; i++)
51  if ( _libroar_notes[i].id == note )
52   return _libroar_notes[i].name;
53
54 return NULL;
55}
56
57uint16_t   roar_midi_name2note   (char * note) {
58 int i;
59
60 for (i = 0; _libroar_notes[i].name != NULL; i++)
61  if ( strcasecmp(_libroar_notes[i].name, note) == 0 )
62   return _libroar_notes[i].id;
63
64 return ROAR_MIDI_NOTE_NONE;
65}
66
67float          roar_midi_note2freq   (uint16_t note) {
68 int i;
69
70 for (i = 0; _libroar_notes[i].name != NULL; i++)
71  if ( _libroar_notes[i].id == note )
72   return _libroar_notes[i].freq;
73
74 return -1;
75}
76
77int            roar_midi_find_octave (char * note);
78int            roar_midi_add_octave  (struct roar_note_octave * note) {
79 note->name[0] = 0;
80 return -1;
81}
82
83int            roar_midi_notefill    (struct roar_note_octave * note) {
84 int oct;
85
86 if ( !note )
87  return -1;
88
89 if ( note->note && note->name[0] == 0 ) {
90  roar_midi_add_octave(note);
91 } else if ( !note->note && note->name[0] != 0 ) {
92  return -1;
93 }
94
95 oct = 1 << abs(note->octave);
96
97 note->freq = roar_midi_note2freq(note->note);
98
99 // TODO: fix this: freq is freq*2^octave
100 if ( note->octave < 0 ) {
101  note->freq /= oct;
102 } else {
103  note->freq *= oct;
104 }
105
106 return 0;
107}
108
109int roar_midi_gen_tone (struct roar_note_octave * note, int16_t * samples, float t, int rate, int channels, int type, void * opts) {
110#ifdef ROAR_HAVE_LIBM
111 int i, c;
112 float ct;
113 float step = M_PI*2*note->freq/rate;
114 int16_t s;
115 float (*op)(float x) = NULL;
116
117/*
118 rate: 1/s
119 t   : 1s
120 freq: 1/s
121 rew : 1s
122*/
123
124 if ( type == ROAR_MIDI_TYPE_SINE ) {
125  op = sinf;
126 } else {
127  return -1;
128 }
129
130 if ( op == NULL )
131  return -1;
132
133 for (ct = 0, i = 0; ct <= t; ct += step, i += channels) {
134  s = 32767*op(ct);
135
136  for (c = 0; c < channels; c++)
137   samples[i+c] = s;
138 }
139
140 return 0;
141#else
142 return -1;
143#endif
144}
145
146
147int roar_midi_play_note  (struct roar_stream * stream, struct roar_note_octave * note, float len) {
148 return -1;
149}
150
151int roar_midi_basic_init (struct roar_midi_basic_state * state) {
152 if (!state)
153  return -1;
154
155 state->len.mul = 1;
156 state->len.div = 60;
157
158 state->note.note   = ROAR_MIDI_NOTE_NONE;
159 state->note.octave = 0;
160
161 return 0;
162}
163
164int roar_midi_basic_play (struct roar_stream * stream, struct roar_midi_basic_state * state, char * notes) {
165 struct roar_midi_basic_state is;
166 char   cn[ROAR_MIDI_MAX_NOTENAME_LEN+1] = {0};
167 int i;
168 int have = 0;
169 struct roar_note_octave * n;
170
171 if ( !notes )
172  return -1;
173
174 if ( state == NULL ) {
175  state = &is;
176  roar_midi_basic_init(state);
177 }
178
179 n = &(state->note);
180
181 for (; *notes != 0; notes++) {
182  if ( *notes == '>' ) {
183   n->octave++;
184  } else if ( *notes == '<' ) {
185   n->octave--;
186  } else if ( *notes != ' ' ) {
187   have++;
188  }
189
190  if (have) {
191   roar_midi_play_note(stream, n, 60 * state->len.mul / state->len.div);
192   have = 0;
193  }
194 }
195
196 return 0;
197}
198
199//ll
Note: See TracBrowser for help on using the repository browser.