1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/ags_diatonic_scale.h>
21
22 #include <string.h>
23
24 /**
25 * SECTION:ags_diatonic_scale
26 * @short_description: diatonic scale util
27 * @title: AgsDiatonicScale
28 * @section_id:
29 * @include: ags/audio/ags_diatonic_scale.h
30 *
31 * Utility functions to handle diatonic scale.
32 */
33
34 /**
35 * ags_diatonic_scale_note_to_midi_key:
36 * @note: the note name
37 * @key: return location of MIDI key
38 *
39 * Convert @note to MIDI key and store in @key.
40 *
41 * Returns: the number of chars read
42 *
43 * Since: 3.0.0
44 */
45 guint
ags_diatonic_scale_note_to_midi_key(gchar * note,glong * key)46 ags_diatonic_scale_note_to_midi_key(gchar *note,
47 glong *key)
48 {
49 guint char_count;
50 gint position;
51 glong x_key;
52 int retval;
53 gboolean success;
54
55 if(note == NULL ||
56 note[0] == '\0' ||
57 key == NULL){
58 return(0);
59 }
60
61 x_key = 49;
62
63 char_count = 0;
64
65 success = FALSE;
66
67 switch(note[0]){
68 case 'a':
69 {
70 success = TRUE;
71
72 x_key = 49;
73 }
74 break;
75 case 'h':
76 case 'b':
77 {
78 success = TRUE;
79
80 x_key = 51;
81 }
82 break;
83 case 'c':
84 {
85 success = TRUE;
86
87 x_key = 52;
88 }
89 break;
90 case 'd':
91 {
92 success = TRUE;
93
94 x_key = 54;
95 }
96 break;
97 case 'e':
98 {
99 success = TRUE;
100
101 x_key = 56;
102 }
103 break;
104 case 'f':
105 {
106 success = TRUE;
107
108 x_key = 57;
109 }
110 break;
111 case 'g':
112 {
113 success = TRUE;
114
115 x_key = 59;
116 }
117 break;
118 }
119
120 if(success){
121 char_count = 1;
122 }
123
124 if(!success ||
125 note[1] == '\0'){
126 goto ags_diatonic_scale_note_to_midi_key_COMPLETED;
127 }
128
129 success = FALSE;
130
131 switch(note[1]){
132 case '#':
133 {
134 success = TRUE;
135
136 x_key += 1;
137 }
138 break;
139 case 'b':
140 {
141 success = TRUE;
142
143 x_key -= 1;
144 }
145 break;
146 }
147
148 if(success){
149 char_count = 2;
150 }
151
152 if(!success ||
153 note[2] == '\0'){
154 goto ags_diatonic_scale_note_to_midi_key_COMPLETED;
155 }
156
157 success = FALSE;
158
159 position = -1;
160
161 retval = sscanf(note + 2, "%d", &position);
162
163 if(retval > 0){
164 if(position > 49){
165 x_key += ((position - 1) * 12) - 48;
166 }else if(position < 49){
167 x_key += ((position - 1) * 12) - 48;
168 }
169
170 char_count += retval;
171 }
172
173 ags_diatonic_scale_note_to_midi_key_COMPLETED:
174 key[0] = x_key;
175
176 return(char_count);
177 }
178
179 /**
180 * ags_diatonic_scale_midi_key_to_note:
181 * @key: MIDI key
182 * @note: return location of note name
183 *
184 * Convert MIDI @key to note name and store in @note.
185 *
186 * Returns: the number of chars written
187 *
188 * Since: 3.0.0
189 */
190 guint
ags_diatonic_scale_midi_key_to_note(glong key,gchar ** note)191 ags_diatonic_scale_midi_key_to_note(glong key,
192 gchar **note)
193 {
194 gchar *x_note;
195 gchar *str;
196
197 guint char_count;
198 gint sharp_flats;
199 gint position;
200
201 static const gchar *sharp = "#";
202
203 if(key > 128 ||
204 note == NULL){
205 return(0);
206 }
207
208 x_note = NULL;
209
210 sharp_flats = -1;
211 position = -1;
212
213 switch(key % 12){
214 case 0:
215 {
216 x_note = "a";
217 }
218 break;
219 case 1:
220 {
221 x_note = "a";
222 sharp_flats = 1;
223 }
224 break;
225 case 2:
226 {
227 x_note = "h";
228 }
229 break;
230 case 3:
231 {
232 x_note = "c";
233 }
234 break;
235 case 4:
236 {
237 x_note = "c";
238 sharp_flats = 1;
239 }
240 break;
241 case 5:
242 {
243 x_note = "d";
244 }
245 break;
246 case 6:
247 {
248 x_note = "d";
249 sharp_flats = 1;
250 }
251 break;
252 case 7:
253 {
254 x_note = "e";
255 }
256 break;
257 case 8:
258 {
259 x_note = "f";
260 }
261 break;
262 case 9:
263 {
264 x_note = "f";
265 sharp_flats = 1;
266 }
267 break;
268 case 10:
269 {
270 x_note = "g";
271 }
272 case 11:
273 {
274 x_note = "g";
275 sharp_flats = 1;
276 }
277 break;
278 break;
279 }
280
281 position = floor((gdouble) key / 12.0) + 1;
282
283 if(sharp_flats != -1 &&
284 position != -1){
285 str = g_strdup_printf("%s%s%d",
286 x_note,
287 sharp,
288 position);
289 }else if(position != -1){
290 str = g_strdup_printf("%s%d",
291 x_note,
292 position);
293 }else{
294 str = g_strdup_printf("%s",
295 x_note);
296 }
297
298 char_count = strlen(str);
299 note[0] = str;
300
301 return(char_count);
302 }
303