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 <glib.h>
21 #include <glib-object.h>
22 
23 #include <CUnit/CUnit.h>
24 #include <CUnit/Basic.h>
25 
26 #include <ags/libags.h>
27 #include <ags/libags-audio.h>
28 
29 struct AgsFunctionalFastPitchTestWave
30 {
31   gdouble freq;
32   gdouble key;
33 
34   GList *wave;
35 };
36 
37 gpointer ags_functional_fast_pitch_test_add_thread(gpointer data);
38 
39 int ags_functional_fast_pitch_test_init_suite();
40 int ags_functional_fast_pitch_test_clean_suite();
41 
42 void ags_functional_fast_pitch_test_pitch_up();
43 void ags_functional_fast_pitch_test_pitch_down();
44 
45 struct AgsFunctionalFastPitchTestWave* ags_functional_fast_pitch_test_alloc(GList *template_wave);
46 
47 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS (2)
48 
49 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE (44100)
50 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE (1024)
51 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT (AGS_SOUNDCARD_SIGNED_16_BIT)
52 
53 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_VOLUME (1.0)
54 
55 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY (0.0)
56 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ (440.0)
57 
58 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_TUNE (100.0)
59 
60 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_DELAY (8000000)
61 
62 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_END_KEY (48.0)
63 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_FRAME_COUNT (5 * 44100)
64 
65 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_DOWN_END_KEY (-48.0)
66 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_DOWN_FRAME_COUNT (5 * 44100)
67 
68 #define AGS_FUNCTIONAL_FAST_PITCH_TEST_CONFIG "[generic]\n"	\
69   "autosave-thread=false\n"					\
70   "simple-file=true\n"						\
71   "disable-feature=experimental\n"				\
72   "segmentation=4/4\n"						\
73   "\n"								\
74   "[thread]\n"							\
75   "model=super-threaded\n"					\
76   "super-threaded-scope=audio\n"				\
77   "lock-global=ags-thread\n"					\
78   "lock-parent=ags-recycling-thread\n"				\
79   "thread-pool-max-unused-threads=8\n"				\
80   "max-precision=125\n"						\
81   "\n"								\
82   "[soundcard-0]\n"						\
83   "backend=alsa\n"						\
84   "device=default\n"						\
85   "samplerate=44100\n"						\
86   "buffer-size=1024\n"						\
87   "pcm-channels=2\n"						\
88   "dsp-channels=2\n"						\
89   "format=16\n"							\
90   "\n"								\
91   "[recall]\n"							\
92   "auto-sense=true\n"						\
93   "\n"
94 
95 GThread *add_thread = NULL;
96 
97 AgsAudioApplicationContext *audio_application_context;
98 
99 AgsAudio *output_panel;
100 AgsAudio *wave_player;
101 
102 GObject *output_soundcard;
103 
104 gpointer
ags_functional_fast_pitch_test_add_thread(gpointer data)105 ags_functional_fast_pitch_test_add_thread(gpointer data)
106 {
107   CU_pSuite pSuite = NULL;
108 
109   putenv("LC_ALL=C");
110   putenv("LANG=C");
111 
112   putenv("LADSPA_PATH=\"\"");
113   putenv("DSSI_PATH=\"\"");
114   putenv("LV2_PATH=\"\"");
115 
116   /* initialize the CUnit test registry */
117   if(CUE_SUCCESS != CU_initialize_registry()){
118     exit(CU_get_error());
119   }
120 
121   /* add a suite to the registry */
122   pSuite = CU_add_suite("AgsFunctionalFastPitchTest", ags_functional_fast_pitch_test_init_suite, ags_functional_fast_pitch_test_clean_suite);
123 
124   if(pSuite == NULL){
125     CU_cleanup_registry();
126 
127     exit(CU_get_error());
128   }
129 
130   /* add the tests to the suite */
131   if((CU_add_test(pSuite, "test of ags_filter_util.h doing pitch up", ags_functional_fast_pitch_test_pitch_up) == NULL) ||
132      (CU_add_test(pSuite, "test of ags_filter_util.h doing pitch down", ags_functional_fast_pitch_test_pitch_down) == NULL)){
133     CU_cleanup_registry();
134 
135     exit(CU_get_error());
136   }
137 
138   /* Run all tests using the CUnit Basic interface */
139   CU_basic_set_mode(CU_BRM_VERBOSE);
140   CU_basic_run_tests();
141 
142   CU_cleanup_registry();
143 
144   exit(CU_get_error());
145 }
146 
147 /* The suite initialization function.
148  * Opens the temporary file used by the tests.
149  * Returns zero on success, non-zero otherwise.
150  */
151 int
ags_functional_fast_pitch_test_init_suite()152 ags_functional_fast_pitch_test_init_suite()
153 {
154   AgsChannel *channel, *link;
155 
156   AgsConfig *config;
157 
158   GList *start_list;
159 
160   guint i;
161 
162   GError *error;
163 
164   ags_priority_load_defaults(ags_priority_get_instance());
165 
166   config = ags_config_get_instance();
167   ags_config_load_from_data(config,
168 			    AGS_FUNCTIONAL_FAST_PITCH_TEST_CONFIG,
169 			    strlen(AGS_FUNCTIONAL_FAST_PITCH_TEST_CONFIG));
170 
171   /* audio application context */
172   audio_application_context = (AgsApplicationContext *) ags_audio_application_context_new();
173   g_object_ref(audio_application_context);
174 
175   ags_application_context_prepare(audio_application_context);
176   ags_application_context_setup(audio_application_context);
177 
178   /* output soundcard */
179   output_soundcard = audio_application_context->soundcard->data;
180 
181   start_list = NULL;
182 
183   /* output panel */
184   output_panel = ags_audio_new(output_soundcard);
185 
186   g_object_ref(output_panel);
187   start_list = g_list_prepend(start_list,
188 			      output_panel);
189 
190   ags_audio_set_flags(output_panel, (AGS_AUDIO_SYNC));
191 
192   ags_audio_set_audio_channels(output_panel,
193 			       AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS, 0);
194 
195   ags_audio_set_pads(output_panel,
196 		     AGS_TYPE_OUTPUT,
197 		     1, 0);
198   ags_audio_set_pads(output_panel,
199 		     AGS_TYPE_INPUT,
200 		     1, 0);
201 
202   /* ags-play */
203   ags_recall_factory_create(output_panel,
204 			    NULL, NULL,
205 			    "ags-play-master",
206 			    0, AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS,
207 			    0, 1,
208 			    (AGS_RECALL_FACTORY_INPUT,
209 			     AGS_RECALL_FACTORY_PLAY |
210 			     AGS_RECALL_FACTORY_ADD),
211 			    0);
212 
213   ags_connectable_connect(AGS_CONNECTABLE(output_panel));
214 
215   /* wave player */
216   wave_player = ags_audio_new(output_soundcard);
217 
218   g_object_ref(wave_player);
219   start_list = g_list_prepend(start_list,
220 			      wave_player);
221 
222   ags_audio_set_flags(wave_player, (AGS_AUDIO_SYNC |
223 				    AGS_AUDIO_OUTPUT_HAS_RECYCLING |
224 				    AGS_AUDIO_INPUT_HAS_RECYCLING));
225   ags_audio_set_ability_flags(wave_player, (AGS_SOUND_ABILITY_WAVE));
226 
227   ags_audio_set_audio_channels(wave_player,
228 			       AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS, 0);
229 
230   ags_audio_set_pads(wave_player,
231 		     AGS_TYPE_OUTPUT,
232 		     1, 0);
233   ags_audio_set_pads(wave_player,
234 		     AGS_TYPE_INPUT,
235 		     1, 0);
236 
237   channel = wave_player->output;
238 
239   for(i = 0; i < AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS; i++){
240     ags_channel_set_ability_flags(channel, (AGS_SOUND_ABILITY_WAVE));
241 
242     channel = channel->next;
243   }
244 
245   /* ags-play-wave */
246   ags_recall_factory_create(wave_player,
247 			    NULL, NULL,
248 			    "ags-play-wave",
249 			    0, AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS,
250 			    0, 1,
251 			    (AGS_RECALL_FACTORY_OUTPUT |
252 			     AGS_RECALL_FACTORY_ADD |
253 			     AGS_RECALL_FACTORY_PLAY),
254 			    0);
255 
256   ags_connectable_connect(AGS_CONNECTABLE(wave_player));
257 
258   /*  */
259   start_list = g_list_reverse(start_list);
260   ags_sound_provider_set_audio(AGS_SOUND_PROVIDER(audio_application_context),
261 			       start_list);
262 
263   /* link */
264   channel = output_panel->input;
265   link = wave_player->output;
266 
267   for(i = 0; i < AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS; i++){
268     error = NULL;
269     ags_channel_set_link(channel,
270 			 link,
271 			 &error);
272 
273     channel = channel->next;
274     link = link->next;
275   }
276 
277   return(0);
278 }
279 
280 /* The suite cleanup function.
281  * Closes the temporary file used by the tests.
282  * Returns zero on success, non-zero otherwise.
283  */
284 int
ags_functional_fast_pitch_test_clean_suite()285 ags_functional_fast_pitch_test_clean_suite()
286 {
287   g_object_unref(audio_application_context);
288 
289   return(0);
290 }
291 
292 struct AgsFunctionalFastPitchTestWave*
ags_functional_fast_pitch_test_alloc(GList * template_wave)293 ags_functional_fast_pitch_test_alloc(GList *template_wave)
294 {
295   struct AgsFunctionalFastPitchTestWave *test_wave;
296 
297   guint i_stop, j_stop;
298   guint i, j;
299 
300   test_wave = (struct AgsFunctionalFastPitchTestWave *) malloc(sizeof(struct AgsFunctionalFastPitchTestWave));
301 
302   test_wave->key = AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY;
303   test_wave->freq = AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ;
304 
305   test_wave->wave = NULL;
306 
307   /* wave */
308   i_stop = g_list_length(template_wave);
309 
310   for(i = 0; i < i_stop; i++){
311     AgsWave *wave, *current_wave;
312 
313     GList *template_buffer;
314 
315     current_wave = AGS_WAVE(template_wave->data);
316 
317     /* instantiate wave */
318     wave = ags_wave_new(current_wave->audio,
319 			current_wave->line);
320 
321     ags_timestamp_set_ags_offset(wave,
322 				 ags_timestamp_get_ags_offset(current_wave));
323 
324     g_object_set(wave,
325 		 "samplerate", AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
326 		 "buffer-size", AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
327 		 "format", AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT,
328 		 NULL);
329 
330     test_wave->wave = ags_wave_add(test_wave->wave,
331 				   wave);
332 
333     /* buffer */
334     template_buffer = current_wave->buffer;
335 
336     j_stop = g_list_length(current_wave->buffer);
337 
338     for(j = 0; j < j_stop; j++){
339       AgsBuffer *buffer, *current_buffer;
340 
341       current_buffer = AGS_BUFFER(template_buffer->data);
342 
343       /* duplicate buffer */
344       buffer = ags_buffer_duplicate(current_buffer);
345       ags_wave_add_buffer(wave,
346 			  buffer,
347 			  FALSE);
348 
349       /* iterate buffer */
350       template_buffer = template_buffer->next;
351     }
352 
353     /* iterate wave */
354     template_wave = template_wave->next;
355   }
356 
357   return(test_wave);
358 }
359 
360 void
ags_functional_fast_pitch_test_pitch_up()361 ags_functional_fast_pitch_test_pitch_up()
362 {
363   AgsTaskLauncher *task_launcher;
364 
365   GList *start_wave, *wave;
366   GList *start_list, *list;
367 
368   gint i, j, k;
369   gboolean success;
370 
371   start_wave = NULL;
372 
373   for(i = 0; i < AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS; i++){
374     AgsWave *current_wave;
375 
376     current_wave = ags_wave_new(wave_player,
377 				i);
378 
379     g_object_set(current_wave,
380 		 "samplerate", AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
381 		 "buffer-size", AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
382 		 "format", AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT,
383 		 NULL);
384 
385     start_wave = ags_wave_add(start_wave,
386 			      current_wave);
387 
388     for(j = 0; j < floor(AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_FRAME_COUNT / AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE); j++){
389       AgsBuffer *buffer;
390 
391       gdouble phase;
392 
393       buffer = ags_buffer_new();
394       g_object_set(buffer,
395 		   "samplerate", AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
396 		   "buffer-size", AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
397 		   "format", AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT,
398 		   "x", (guint64) (j * AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE),
399 		   NULL);
400       ags_wave_add_buffer(current_wave,
401 			  buffer,
402 			  FALSE);
403 
404       phase = buffer->x % (guint) floor(AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE / AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ);
405       ags_synth_util_sin(buffer->data,
406 			 AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ, phase, AGS_FUNCTIONAL_FAST_PITCH_TEST_VOLUME,
407 			 AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE, ags_audio_buffer_util_format_from_soundcard(AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT),
408 			 0, AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE);
409     }
410   }
411 
412   start_list = NULL;
413 
414   for(i = (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY; i <= (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_END_KEY; i++){
415     struct AgsFunctionalFastPitchTestWave *test_wave;
416 
417     GList *pitch_wave;
418 
419     test_wave = ags_functional_fast_pitch_test_alloc(start_wave);
420     start_list = g_list_prepend(start_list,
421 				test_wave);
422 
423     pitch_wave = test_wave->wave;
424 
425     while(pitch_wave != NULL){
426       GList *pitch_buffer;
427 
428       pitch_buffer = AGS_WAVE(pitch_wave->data)->buffer;
429 
430       for(k = 0; pitch_buffer != NULL; k++){
431 	switch(AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT){
432 	case AGS_SOUNDCARD_SIGNED_16_BIT:
433 	{
434 	  ags_fast_pitch_util_compute_s16(AGS_BUFFER(pitch_buffer->data)->data,
435 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
436 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
437 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY,
438 					  (gdouble) i * AGS_FUNCTIONAL_FAST_PITCH_TEST_TUNE);
439 	}
440 	break;
441 	}
442 
443 	pitch_buffer = pitch_buffer->next;
444       }
445 
446       pitch_wave = pitch_wave->next;
447     }
448   }
449 
450   start_list = g_list_reverse(start_list);
451 
452   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(audio_application_context));
453 
454   list = start_list;
455   success = TRUE;
456 
457   for(i = (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY; i <= (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_END_KEY; i++){
458     AgsStartAudio *start_audio;
459     AgsStartSoundcard *start_soundcard;
460     AgsCancelAudio *cancel_audio;
461 
462     struct AgsFunctionalFastPitchTestWave *test_wave;
463 
464     GList *task;
465 
466     g_message("playing key = %d", i);
467 
468     test_wave = list->data;
469 
470     wave_player->wave = test_wave->wave;
471 
472     /* start audio and soundcard task */
473     task = NULL;
474     start_audio = ags_start_audio_new(wave_player,
475 				      AGS_SOUND_SCOPE_WAVE);
476     task = g_list_prepend(task,
477 			  start_audio);
478 
479     start_soundcard = ags_start_soundcard_new();
480     task = g_list_prepend(task,
481 			  start_soundcard);
482 
483     ags_task_launcher_add_task_all(task_launcher,
484 				   task);
485 
486     /* delay */
487     usleep(AGS_FUNCTIONAL_FAST_PITCH_TEST_DELAY);
488 
489     /* create cancel task */
490     cancel_audio = ags_cancel_audio_new(wave_player,
491 					AGS_SOUND_SCOPE_WAVE);
492 
493     /* append AgsCancelAudio */
494     ags_task_launcher_add_task(task_launcher,
495 			       (AgsTask *) cancel_audio);
496 
497     usleep(1500000);
498 
499     /* iterate */
500     list = list->next;
501   }
502 
503   CU_ASSERT(success == TRUE);
504 }
505 
506 void
ags_functional_fast_pitch_test_pitch_down()507 ags_functional_fast_pitch_test_pitch_down()
508 {
509   AgsTaskLauncher *task_launcher;
510 
511   GList *start_wave, *wave;
512   GList *start_list, *list;
513 
514   gint i, j, k;
515   gboolean success;
516 
517   start_wave = NULL;
518 
519   for(i = 0; i < AGS_FUNCTIONAL_FAST_PITCH_TEST_AUDIO_CHANNELS; i++){
520     AgsWave *current_wave;
521 
522     current_wave = ags_wave_new(wave_player,
523 				i);
524 
525     g_object_set(current_wave,
526 		 "samplerate", AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
527 		 "buffer-size", AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
528 		 "format", AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT,
529 		 NULL);
530 
531     start_wave = ags_wave_add(start_wave,
532 			      current_wave);
533 
534     for(j = 0; j < floor(AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_FRAME_COUNT / AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE); j++){
535       AgsBuffer *buffer;
536 
537       gdouble phase;
538 
539       buffer = ags_buffer_new();
540       g_object_set(buffer,
541 		   "samplerate", AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
542 		   "buffer-size", AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
543 		   "format", AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT,
544 		   "x", (guint64) (j * AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE),
545 		   NULL);
546       ags_wave_add_buffer(current_wave,
547 			  buffer,
548 			  FALSE);
549 
550       phase = buffer->x % (guint) floor(AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE / AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ);
551       ags_synth_util_sin(buffer->data,
552 			 AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_FREQ, phase, AGS_FUNCTIONAL_FAST_PITCH_TEST_VOLUME,
553 			 AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE, ags_audio_buffer_util_format_from_soundcard(AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT),
554 			 0, AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE);
555     }
556   }
557 
558   start_list = NULL;
559 
560   for(i = (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY; i >= (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_DOWN_END_KEY; i--){
561     struct AgsFunctionalFastPitchTestWave *test_wave;
562 
563     GList *pitch_wave;
564 
565     test_wave = ags_functional_fast_pitch_test_alloc(start_wave);
566     start_list = g_list_prepend(start_list,
567 				test_wave);
568 
569     pitch_wave = test_wave->wave;
570 
571     while(pitch_wave != NULL){
572       GList *pitch_buffer;
573 
574       pitch_buffer = AGS_WAVE(pitch_wave->data)->buffer;
575 
576       for(k = 0; k < floor(AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_UP_FRAME_COUNT / AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE); k++){
577 	switch(AGS_FUNCTIONAL_FAST_PITCH_TEST_FORMAT){
578 	case AGS_SOUNDCARD_SIGNED_16_BIT:
579 	{
580 	  ags_fast_pitch_util_compute_s16(AGS_BUFFER(pitch_buffer->data)->data,
581 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_BUFFER_SIZE,
582 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_SAMPLERATE,
583 					  AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY,
584 					  (gdouble) i * AGS_FUNCTIONAL_FAST_PITCH_TEST_TUNE);
585 	}
586 	break;
587 	}
588 
589 	pitch_buffer = pitch_buffer->next;
590       }
591 
592       pitch_wave = pitch_wave->next;
593     }
594   }
595 
596   start_list = g_list_reverse(start_list);
597 
598   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(audio_application_context));
599 
600   list = start_list;
601   success = TRUE;
602 
603   for(i = (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_BASE_KEY; i >= (gint) AGS_FUNCTIONAL_FAST_PITCH_TEST_PITCH_DOWN_END_KEY; i--){
604     AgsStartAudio *start_audio;
605     AgsStartSoundcard *start_soundcard;
606     AgsCancelAudio *cancel_audio;
607 
608     struct AgsFunctionalFastPitchTestWave *test_wave;
609 
610     GList *task;
611 
612     g_message("playing key = %d", i);
613 
614     test_wave = list->data;
615 
616     wave_player->wave = test_wave->wave;
617 
618     /* start audio and soundcard task */
619     task = NULL;
620     start_audio = ags_start_audio_new(wave_player,
621 				      AGS_SOUND_SCOPE_WAVE);
622     task = g_list_prepend(task,
623 			  start_audio);
624 
625     start_soundcard = ags_start_soundcard_new();
626     task = g_list_prepend(task,
627 			  start_soundcard);
628 
629     ags_task_launcher_add_task_all(task_launcher,
630 				   task);
631 
632     /* delay */
633     usleep(AGS_FUNCTIONAL_FAST_PITCH_TEST_DELAY);
634 
635     /* create cancel task */
636     cancel_audio = ags_cancel_audio_new(wave_player,
637 					AGS_SOUND_SCOPE_WAVE);
638 
639     /* append AgsCancelAudio */
640     ags_task_launcher_add_task(task_launcher,
641 			       (AgsTask *) cancel_audio);
642 
643     usleep(1500000);
644 
645     /* iterate */
646     list = list->next;
647   }
648 
649   CU_ASSERT(success == TRUE);
650 }
651 
652 int
main(int argc,char ** argv)653 main(int argc, char **argv)
654 {
655   add_thread = g_thread_new("libags_audio.so - functional fast pitch test",
656 			    ags_functional_fast_pitch_test_add_thread,
657 			    NULL);
658 
659   g_main_loop_run(g_main_loop_new(g_main_context_default(),
660 				  FALSE));
661 
662   g_thread_join(add_thread);
663 
664   return(-1);
665 }
666 
667