Tscope5
audio.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // __ ______
4 // / /_______________ ____ ___ / ____/
5 // / __/ ___/ ___/ __ \/ __ \/ _ \ /___ )
6 // / /_(__ ) /__/ /_/ / /_/ / __/ ____/ /
7 // \__/____/\___/\____/ .___/\___/ /_____/
8 // /_/
9 //
10 /// \file audio.c
11 /// Definitions of audio functions.
12 /// \example audio01.c
13 /// \example audio02.c
14 /// \example audio03.c
15 /// \example audio04.c
16 ////////////////////////////////////////////////////////////////////////////////
17 
18 
19 ////////////////////////////////////////////////////////////////////////////////
20 /// @name Audio parameters
21 /// The parameters of the audio output device (sound card) can be set
22 /// using the functions below.
23 ///
24 /// The audio gain (amplification factor) can be changed at any time.
25 /// All other functions functions in this group have to be called before
26 /// the audio subsystem is loaded
27 /// (i.e. before the first sample is loaded and played)
28 /// and their settings remain unchanged until the end of the program.
29 ///
30 /// The parameter functions also define the settings for samples that
31 /// are created with ts5_alloc_sample().
32 //@{
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include "../include/tscope5/audio.h"
36 #include "../include/tscope5/audio_internal.h"
37 #include "../include/tscope5/system_internal.h"
38 
39 #include <math.h>
40 
41 
42 ////////////////////////////////////////////////////////////////////////////////
43 /// Set the requested samplerate for the audio system.
44 ///
45 /// \param samplerate The samplerate. Can be TS5_11025, TS5_22050 or TS5_44100.
46 ///
47 /// \return The previous requested samplerate.
48 ///
49 /// This function has to be called before the (automatic)
50 /// installation of the audio system.
51 ///
52 /// Once the audio system is installed,
53 /// the sample rate of the system cannot be changed.
54 ///
55 /// This is only a request, the audio driver can choose non-matching values.
56 /// Query the audio system after installation with ts5_get_audio_samplerate()
57 /// for the actual sample rate.
58 ///
59 /// This function also influences the sample rate of samples made by
60 /// ts5_alloc_sample().
61 ///
62 /// The default samplerate is TS5_44100.
63 ////////////////////////////////////////////////////////////////////////////////
64 unsigned int ts5_set_audio_samplerate(unsigned int samplerate)
65 {
67  ts5_install_tscope5("ts5_set_audio_samplerate");
68  }
69 
70  ts5_log(TS5_LOGLEVEL_4, "ts5_set_audio_samplerate(%u)\n", samplerate);
71 
72  unsigned int retval = _ts5_status.audio.samplerate;
73 
74  if (samplerate!=TS5_11025 && samplerate!=TS5_22050 && samplerate!=TS5_44100) {
75  ts5_fatal("ts5_set_audio_samplerate: unknown samplerate requested\n");
76  }
77 
78  _ts5_status.audio.samplerate = samplerate;
79 
80  ts5_log(TS5_LOGLEVEL_4,
81  "ts5_set_audio_samplerate: set sample rate to %u (was %u)\n",
82  _ts5_status.audio.samplerate, retval);
83 
84  return retval;
85 }
86 
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 /// Get the sample rate of the audio system.
90 ///
91 /// \return The sample rate of the audio system as an unsigned integer.
92 ////////////////////////////////////////////////////////////////////////////////
94 {
95  ts5_check_audio("ts5_get_audio_samplerate");
96  ts5_log(TS5_LOGLEVEL_4, "ts5_get_audio_samplerate()\n");
97 
98  return _ts5_status.audio.samplerate;
99 }
100 
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// Set the requested number of channels for the audio system.
104 ///
105 /// \param channels The number of channels. Can be TS5_MONO or TS5_STEREO.
106 ///
107 /// \return The previous requested number of channels.
108 ///
109 /// This function has to be called before the (automatic)
110 /// installation of the audio system.
111 ///
112 /// Once the audio system is installed,
113 /// the number of channels of the system cannot be changed.
114 ///
115 /// This is only a request, the audio driver can choose non-matching values.
116 /// Query the audio system after installation with ts5_get_audio_channels()
117 /// for the actual number of channels.
118 ///
119 /// This function also influences the number of channels of samples
120 /// made by ts5_alloc_sample().
121 ///
122 /// The default number of channels is TS5_STEREO.
123 ////////////////////////////////////////////////////////////////////////////////
124 unsigned int ts5_set_audio_channels(unsigned int channels)
125 {
127  ts5_install_tscope5("ts5_set_audio_channels");
128  }
129 
130  ts5_log(TS5_LOGLEVEL_4, "ts5_set_audio_channels(%d)\n", channels);
131 
132  unsigned int retval = _ts5_status.audio.channels;
133 
134  if (channels!=TS5_MONO && channels!=TS5_STEREO) {
135  ts5_fatal("%s: %s\n", "ts5_set_audio_channels",
136  "unknown number of channels requested");
137  }
138 
139  _ts5_status.audio.channels = channels;
140 
141  ts5_log(TS5_LOGLEVEL_4, "%s: %s %u (was %u)\n",
142  "ts5_set_audio_channels",
143  "set number of channels to",
144  _ts5_status.audio.channels, retval);
145 
146  return retval;
147 }
148 
149 
150 ////////////////////////////////////////////////////////////////////////////////
151 /// Get the number of channels of the audio system.
152 ///
153 /// \return The number of channels of the audio system.
154 ////////////////////////////////////////////////////////////////////////////////
156 {
157  ts5_check_audio("ts5_get_audio_channels");
158  ts5_log(TS5_LOGLEVEL_4, "ts5_get_audio_channels()\n");
159 
160  ALLEGRO_CHANNEL_CONF channels =
161  al_get_voice_channels(_ts5_data.audio.voice);
162 
163  unsigned int retval;
164 
165  if (channels == ALLEGRO_CHANNEL_CONF_1) {
166  retval = TS5_MONO;
167  }
168  else if (channels == ALLEGRO_CHANNEL_CONF_2) {
169  retval = TS5_STEREO;
170  }
171  else {
172  ts5_fatal("%s: %s\n", "ts5_get_audio_channels",
173  "got an unknown number of channels");
174  retval = 0;
175  }
176 
177  return retval;
178 }
179 
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Set the sample depth for the audio system.
183 ///
184 /// \param depth The sample depth. Can be TS5_INTEGER or TS5_FLOAT.
185 ///
186 /// \return The previous requested sample depth.
187 ///
188 /// This function has to be called before the (automatic)
189 /// installation of the audio system.
190 ///
191 /// Once the audio system is installed,
192 /// the sample depth of the system cannot be changed.
193 ///
194 /// This is only a request, the audio driver can choose non-matching values.
195 /// Query the audio system after installation with ts5_get_audio_depth()
196 /// for the actual sample depth.
197 ///
198 /// This function also influences the sample depth of samples
199 /// made by ts5_alloc_sample().
200 ///
201 /// The default sample depth is TS5_FLOAT.
202 ///
203 /// \todo currently has no effect.
204 /// The voice will be integer and the mixer floating point.
205 ////////////////////////////////////////////////////////////////////////////////
206 int ts5_set_audio_depth(int depth)
207 {
209  ts5_install_tscope5("ts5_set_audio_depth");
210  }
211 
212  ts5_log(TS5_LOGLEVEL_4, "ts5_set_audio_depth(%d)\n", depth);
213 
214  int retval = _ts5_status.audio.depth;
215 
216  if (depth!=TS5_INTEGER && depth!=TS5_FLOAT) {
217  ts5_fatal("ts5_set_audio_depth: unknown sample depth requested\n");
218  }
219 
220  _ts5_status.audio.depth = depth;
221 
222  ts5_log(TS5_LOGLEVEL_4, "%s: %s %d (was %d)\n",
223  "ts5_set_audio_depth", "set sample depth to",
224  _ts5_status.audio.depth, retval);
225 
226  return retval;
227 }
228 
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Get the sample depth of the audio system.
232 ///
233 /// \return The sample depth of the audio system.
234 ////////////////////////////////////////////////////////////////////////////////
236 {
237  ts5_check_audio("ts5_get_audio_depth");
238  ts5_log(TS5_LOGLEVEL_4, "ts5_get_audio_depth()\n");
239 
240  ALLEGRO_AUDIO_DEPTH depth =
241  al_get_voice_depth(_ts5_data.audio.voice);
242 
243  if (depth != TS5_INTEGER && depth !=TS5_FLOAT) {
244  ts5_fatal("ts5_get_audio_depth: got an unknown sample depth\n");
245  }
246 
247  return depth;
248 }
249 
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Set the gain (amplification factor) of the audio system.
253 ///
254 /// \param gain The gain.
255 /// 0.0 = silent, 0.5=half, 1.0 = untouched, 2.0 = double, ...
256 ///
257 /// \return The previous setting.
258 ///
259 /// The default gain is 1.0.
260 ////////////////////////////////////////////////////////////////////////////////
261 double ts5_set_audio_gain(double gain)
262 {
264  ts5_install_tscope5("ts5_set_audio_gain");
265  }
266 
267  ts5_log(TS5_LOGLEVEL_4, "ts5_set_audio_gain(%f)\n", gain);
268 
269  double retval = _ts5_status.audio.gain;
270 
271  if (gain<0.0) {
272  ts5_fatal("ts5_set_audio_gain: gain should be >= 0.0\n");
273  }
274 
275  _ts5_status.audio.gain = gain;
276 
277  if (!al_set_mixer_gain(_ts5_data.audio.mixer, gain)) {
278  ts5_fatal("ts5_set_audio_gain: could not change audio gain\n");
279  }
280 
281  ts5_log(TS5_LOGLEVEL_4, "ts5_set_audio_gain: set gain to %f (was %f)\n",
282  _ts5_status.audio.gain, retval);
283 
284  return retval;
285 }
286 
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Get the gain of the audio system.
290 ///
291 /// \return The gain of the audio system.
292 ////////////////////////////////////////////////////////////////////////////////
294 {
295  ts5_check_audio("ts5_get_audio_gain");
296  ts5_log(TS5_LOGLEVEL_4, "ts5_get_audio_gain()\n");
297 
298  return _ts5_status.audio.gain;
299 }
300 
301 
302 ////////////////////////////////////////////////////////////////////////////////
303 //@}
304 ////////////////////////////////////////////////////////////////////////////////
305 
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 /// @name Loading samples
309 /// Samples can either be read from a file, or empty samples can be generated.
310 ///
311 /// Empty samples can be used for generating simple sounds
312 /// or for recording vocal responses.
313 ///
314 /// Most samples (samples that contain less than 2^24 sample values)
315 /// can be read completely into memory using ts5_read_sample().
316 /// Longer samples should be loaded with ts5_read_long_sample().
317 /// These will be streamed
318 /// (i.e. they will be divided in parts that are read when necessary).
319 //@{
320 ////////////////////////////////////////////////////////////////////////////////
321 
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Create an empty sample.
325 ///
326 /// \param length Length of the sample in seconds.
327 ///
328 /// \return A pointer to the newly created sample.
329 ///
330 /// A Sample's samplerate, channels and depth are set by
331 /// ts5_set_audio_samplerate(), ts5_set_audio_channels()
332 /// and ts5_set_audio_depth()
333 ////////////////////////////////////////////////////////////////////////////////
334 TS5_SAMPLE *ts5_alloc_sample(double length)
335 {
336  ts5_check_audio("ts5_alloc_sample");
337  ts5_log(TS5_LOGLEVEL_2, "ts5_alloc_sample(%f)\n", length);
338 
339  // create the sample structure
340  TS5_SAMPLE *sample = NULL;
341  sample = (TS5_SAMPLE *)al_malloc(sizeof(TS5_SAMPLE));
342 
343  if (!sample) {
344  ts5_fatal("ts5_alloc_sample: could not allocate sample\n");
345  }
346 
347  sample->issample = 1;
348  sample->isbuffer = 1;
349  sample->isfilestream = 0;
350  sample->ismemorystream = 0;
351  sample->stream = NULL;
352 
353  // get the paramters for the sample
354  unsigned int samples = length * _ts5_status.audio.samplerate;
355  ALLEGRO_CHANNEL_CONF channels = 0;
356 
357  if (_ts5_status.audio.channels==TS5_MONO) {
358  channels=ALLEGRO_CHANNEL_CONF_1;
359  }
360  else if (_ts5_status.audio.channels==TS5_STEREO) {
361  channels=ALLEGRO_CHANNEL_CONF_2;
362  }
363  else {
364  ts5_fatal("%s: %s\n", "ts5_alloc_sample",
365  "unknown channel configuration requested");
366  }
367 
368  unsigned int sample_size =
369  al_get_channel_count(channels) *
370  al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
371 
372  unsigned int bytes = samples * sample_size;
373 
374  sample->start_time = 0.0;
375 
376  // create the buffer
377  sample->buffer = al_malloc(bytes);
378  if (!sample->buffer) {
379  ts5_fatal("ts5_alloc_sample: could not allocate sample buffer\n");
380  }
381 
382  sample->buffer_end = sample->buffer + samples * _ts5_status.audio.channels;
383  sample->buffer_recorder_position = sample->buffer;
384  sample->buffer_voicekey_position = sample->buffer;
385 
386  // create the sample
387  sample->sample = al_create_sample(sample->buffer, samples,
388  _ts5_status.audio.samplerate,
389  ALLEGRO_AUDIO_DEPTH_INT16, channels, 1);
390 
391  if (!sample->sample) {
392  ts5_fatal("ts5_alloc_sample: could not create sample\n");
393  }
394 
395 
396  // create the sample instance
397  sample->instance = al_create_sample_instance(NULL);
398 
399  if (!sample->instance) {
400  ts5_fatal("ts5_alloc_sample: could not create sample instance\n");
401  }
402 
403  if (!al_set_sample(sample->instance, sample->sample)) {
404  ts5_fatal("%s: %s\n", "ts5_alloc_sample",
405  "could not attach sample to sample instance");
406  }
407 
408  if (!al_attach_sample_instance_to_mixer
409  (sample->instance, _ts5_data.audio.mixer)) {
410  ts5_fatal("%s: %s\n", "ts5_alloc_sample",
411  "could not attach sample instance to mixer");
412  }
413 
414  al_set_sample_instance_playing(sample->instance, 0);
415 
416  // voice key
417  int nslices = length * 1000;
418  sample->voicekey = (double *)al_malloc(nslices * sizeof(double));
419  sample->voicekey_position = sample->voicekey;
420  sample->voicekey_end = sample->voicekey + nslices;
421  sample->voicekey_num_samples = (int *)al_malloc(nslices * sizeof(int));
422  sample->last_state_toggle_time = -1000;
423  sample->previous_state = 0;
424 
425  return sample;
426 }
427 
428 
429 ////////////////////////////////////////////////////////////////////////////////
430 /// Open a sample from a file.
431 ///
432 /// \param file Path to the sample file.
433 ///
434 /// \return A pointer to the newly created sample.
435 ///
436 /// Available sample types are: wav, flac, ogg, it, mod, s3m, xm.
437 ///
438 /// The file is read from disk all at once.
439 ////////////////////////////////////////////////////////////////////////////////
440 TS5_SAMPLE *ts5_read_sample(const char *file)
441 {
442  ts5_check_audio("ts5_read_sample");
443  ts5_log(TS5_LOGLEVEL_2, "ts5_read_sample(%s)\n", file);
444 
445  TS5_SAMPLE *sample = NULL;
446  sample = (TS5_SAMPLE *)al_malloc(sizeof(TS5_SAMPLE));
447 
448  if (!sample) {
449  ts5_fatal("ts5_read_sample: could not allocate sample\n");
450  }
451 
452  sample->issample = 1;
453  sample->isbuffer = 0;
454  sample->isfilestream = 0;
455  sample->ismemorystream = 0;
456 
457  sample->sample = NULL;
458  sample->sample = al_load_sample(file);
459 
460  if (!sample->sample) {
461  ts5_fatal("ts5_read_sample: could not read sample\n");
462  }
463 
464  sample->instance = NULL;
465  sample->instance = al_create_sample_instance(NULL);
466 
467  if (!sample->instance) {
468  ts5_fatal("ts5_read_sample: could not create sample instance\n");
469  }
470 
471  if (!al_set_sample(sample->instance, sample->sample)) {
472  ts5_fatal("%s: %s\n", "ts5_read_sample",
473  "could not attach sample to sample instance");
474  }
475 
476  if (!al_attach_sample_instance_to_mixer
477  (sample->instance, _ts5_data.audio.mixer)) {
478  ts5_fatal("%s: %s\n", "ts5_read_sample",
479  "could not attach sample instance to mixer");
480  }
481 
482  al_set_sample_instance_playing(sample->instance, 0);
483 
484  sample->stream = NULL;
485 
486  sample->start_time = 0.0;
487 
488  sample->buffer = NULL;
489  sample->buffer_end = NULL;
490  sample->buffer_recorder_position = NULL;
491  sample->buffer_voicekey_position = NULL;
492 
493  int nslices = 0;
494  sample->voicekey = NULL;
495  sample->voicekey_position = NULL;
496  sample->voicekey_end = NULL;
497  sample->voicekey_num_samples = NULL;
498 
499  // for 16 bit samples we have access tot the sample buffer
500  // so we can run an offline voice key
501  if (al_get_sample_depth(sample->sample) == ALLEGRO_AUDIO_DEPTH_INT16) {
502 
503  sample->isbuffer = 1;
504 
505  sample->buffer = (int16_t *)al_get_sample_data(sample->sample);
506  sample->buffer_end = sample->buffer +
507  al_get_sample_length(sample->sample) *
508  ts5_get_sample_channels(sample);
509 
510  sample->buffer_recorder_position = sample->buffer_end;
511  sample->buffer_voicekey_position = sample->buffer;
512 
513  nslices = al_get_sample_length(sample->sample) * 1000;
514  sample->voicekey = (double *)al_malloc(nslices * sizeof(double));
515  sample->voicekey_position = sample->voicekey;
516  sample->voicekey_end = sample->voicekey + nslices;
517  sample->voicekey_num_samples = (int *)al_malloc(nslices * sizeof(int));
518  sample->last_state_toggle_time = -1000;
519  sample->previous_state = 0;
520  }
521 
522  return sample;
523 }
524 
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Open a long sample from a file.
528 ///
529 /// \param file Path to the sample file.
530 ///
531 /// \return A pointer to the newly created sample.
532 ///
533 /// Available sample types are: wav, flac, ogg, it, mod, s3m, xm.
534 ///
535 /// The file is read from disk as it is needed.
536 ////////////////////////////////////////////////////////////////////////////////
537 TS5_SAMPLE *ts5_read_long_sample(const char *file)
538 {
539  ts5_check_audio("ts5_read_long_sample");
540  ts5_log(TS5_LOGLEVEL_2, "ts5_read_long_sample(%s)\n", file);
541 
542  TS5_SAMPLE *sample = NULL;
543  sample = (TS5_SAMPLE *)al_malloc(sizeof(TS5_SAMPLE));
544 
545  if (!sample) {
546  ts5_fatal("ts5_read_long_sample: could not allocate sample\n");
547  }
548 
549  sample->issample = 0;
550  sample->isbuffer = 0;
551  sample->isfilestream = 1;
552  sample->ismemorystream = 0;
553 
554  sample->sample = NULL;
555  sample->instance = NULL;
556  sample->stream = NULL;
557  sample->stream = al_load_audio_stream(file, 4, 2048);
558 
559  if (!sample->stream) {
560  ts5_fatal("ts5_read_long_sample: could not read sample\n");
561  }
562 
563  if (!al_attach_audio_stream_to_mixer
564  (sample->stream, _ts5_data.audio.mixer)) {
565  ts5_fatal("%s: %s\n", "ts5_read_long_sample",
566  "could not attach sample stream to mixer");
567  }
568 
569  al_set_audio_stream_playing(sample->stream, 0);
570  al_set_audio_stream_playmode(sample->stream, ALLEGRO_PLAYMODE_ONCE);
571 
572  // no start time
573  sample->start_time = 0.0;
574 
575  // no acces to the buffer for file streams
576  sample->buffer = NULL;
577  sample->buffer_end = NULL;
578  sample->buffer_recorder_position = NULL;
579  sample->buffer_voicekey_position = NULL;
580 
581  // no voice key for file streams
582  sample->voicekey = NULL;
583  sample->voicekey_position = NULL;
584  sample->voicekey_end = NULL;
585  sample->voicekey_num_samples = NULL;
586 
587  return sample;
588 }
589 
590 
591 ////////////////////////////////////////////////////////////////////////////////
592 /// Write a sample.
593 ///
594 /// \param file Path to the sample file.
595 /// \param sample Pointer to the sample that will be written.
596 ///
597 /// Only .wav is supported. The file extension should be .wav
598 ////////////////////////////////////////////////////////////////////////////////
599 void ts5_write_sample(const char *file, TS5_SAMPLE *sample)
600 {
601  ts5_check_audio("ts5_write_sample");
602  ts5_log(TS5_LOGLEVEL_2, "ts5_write_sample(%s,%p)\n", file, sample);
603 
604  if (!sample->issample) {
605  ts5_fatal("%s: %s\n", "ts5_write_sample",
606  "writing of streams is not implemented yet\n");
607  }
608 
609  if (!al_save_sample(file, sample->sample)) {
610  ts5_fatal("ts5_write_sample: could not write sample\n");
611  }
612 }
613 
614 
615 ////////////////////////////////////////////////////////////////////////////////
616 /// Free the memory used by a sample.
617 ///
618 /// \param sample Pointer to the sample that will be freed.
619 ///
620 /// This function should be called at the end of the program for
621 /// each sample allocated or read by the user.
622 ////////////////////////////////////////////////////////////////////////////////
623 void ts5_free_sample(TS5_SAMPLE *sample)
624 {
625  ts5_check_audio("ts5_free_sample");
626  ts5_log(TS5_LOGLEVEL_2, "ts5_free_sample(%p)\n", sample);
627 
628  if (sample->issample) {
629  al_set_sample(sample->instance, NULL);
630  al_destroy_sample(sample->sample);
631 
632  al_detach_sample_instance(sample->instance);
633  al_destroy_sample_instance(sample->instance);
634 
635  al_free(sample->voicekey);
636  al_free(sample->voicekey_num_samples);
637  }
638  else if (sample->isfilestream) {
639  al_detach_audio_stream(sample->stream);
640  al_destroy_audio_stream(sample->stream);
641  }
642  else if (sample->ismemorystream) {
643  ts5_fatal("ts5_free_sample: memory streams not implemented yet\n");
644  }
645 
646  al_free(sample);
647 }
648 
649 
650 ////////////////////////////////////////////////////////////////////////////////
651 //@}
652 ////////////////////////////////////////////////////////////////////////////////
653 
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 /// @name Playing samples
657 /// Audio samples can be played using the functions below.
658 ///
659 /// Playing a sample will not block the flow of your program.
660 /// Once a sample starts playing the function call following
661 /// ts5_play_sample() will be executed immediately.
662 //@{
663 ////////////////////////////////////////////////////////////////////////////////
664 
665 
666 ////////////////////////////////////////////////////////////////////////////////
667 /// Start playing a sample.
668 ///
669 /// \param sample Pointer to the sample that will be played.
670 ////////////////////////////////////////////////////////////////////////////////
671 void ts5_play_sample(TS5_SAMPLE *sample)
672 {
673  ts5_check_audio("ts5_play_sample");
674  ts5_log(TS5_LOGLEVEL_5, "ts5_play_sample(%p)\n", sample);
675 
676  if (!sample) {
677  ts5_fatal("ts5_play_sample: sample pointer is null\n");
678  }
679 
680  if (sample->issample) {
681 
682  if (!al_set_sample_instance_playing(sample->instance, 1)) {
683  ts5_fatal("ts5_play_sample: could not play sample\n");
684  }
685  }
686  else if (sample->isfilestream) {
687 
688  if (!al_set_audio_stream_playing(sample->stream, 1)) {
689  ts5_fatal("ts5_play_sample: could not play sample\n");
690  }
691  }
692  else if (sample->ismemorystream) {
693  ts5_fatal("ts5_play_sample: memory streams not implemented yet\n");
694  }
695 }
696 
697 
698 ////////////////////////////////////////////////////////////////////////////////
699 /// Pause playing a sample.
700 ///
701 /// \param sample Pointer to the sample that will be paused.
702 ////////////////////////////////////////////////////////////////////////////////
703 void ts5_pause_sample(TS5_SAMPLE *sample)
704 {
705  ts5_check_audio("ts5_pause_sample");
706  ts5_log(TS5_LOGLEVEL_5, "ts5_pause_sample(%p)\n", sample);
707 
708  if (!sample) {
709  ts5_fatal("ts5_pause_sample: sample pointer is null\n");
710  }
711 
712  if (sample->issample) {
713 
714  if (!al_set_sample_instance_playing(sample->instance, 0)) {
715  ts5_fatal("ts5_pause_sample: could not pause sample\n");
716  }
717  }
718  else if (sample->isfilestream) {
719 
720  if (!al_set_audio_stream_playing(sample->stream, 0)) {
721  ts5_fatal("ts5_pause_sample: could not pause sample\n");
722  }
723  }
724  else if (sample->ismemorystream) {
725  ts5_fatal("memory streams not implemented yet\n");
726  }
727 }
728 
729 
730 ////////////////////////////////////////////////////////////////////////////////
731 /// Stop playing a sample.
732 ///
733 /// \param sample Pointer to the sample that will be stopped.
734 ////////////////////////////////////////////////////////////////////////////////
735 void ts5_stop_sample(TS5_SAMPLE *sample)
736 {
737  ts5_check_audio("ts5_stop_sample");
738  ts5_log(TS5_LOGLEVEL_5, "ts5_stop_sample(%p)\n", sample);
739 
740  if (!sample) {
741  ts5_fatal("ts5_stop_sample: sample pointer is null\n");
742  }
743 
744  if (sample->issample) {
745 
746  if (!al_set_sample_instance_playing(sample->instance, 0)) {
747  ts5_fatal("ts5_stop_sample: could not stop sample\n");
748  }
749 
750  if (!al_set_sample_instance_position(sample->instance, 0)) {
751  ts5_fatal("ts5_stop_sample: could not stop sample\n");
752  }
753  }
754  else if (sample->isfilestream) {
755 
756  al_drain_audio_stream(sample->stream);
757 
758  if (!al_rewind_audio_stream(sample->stream)) {
759  ts5_fatal("ts5_stop_sample: could not rewind sample\n");
760  }
761  }
762  else if (sample->ismemorystream) {
763  ts5_fatal("ts5_stop_sample: memory streams not implemented yet\n");
764  }
765 }
766 
767 
768 ////////////////////////////////////////////////////////////////////////////////
769 /// Query whether a sample is playing.
770 ///
771 /// \param sample Pointer to the sample that will queried.
772 ///
773 /// \return 1 if the sample is playing, 0 if not.
774 ////////////////////////////////////////////////////////////////////////////////
775 int ts5_get_sample_status(TS5_SAMPLE *sample)
776 {
777  ts5_check_audio("ts5_get_sample_status");
778  ts5_log(TS5_LOGLEVEL_5, "ts5_get_sample_status(%p)\n", sample);
779 
780  if (!sample) {
781  ts5_fatal("ts5_get_sample_status: sample pointer is null\n");
782  }
783 
784  int retval = 0;
785 
786  if (sample->issample) {
787  retval = al_get_sample_instance_playing(sample->instance);
788  }
789  else if (sample->isfilestream) {
790  retval = al_get_audio_stream_playing(sample->stream);
791  }
792  else if (sample->ismemorystream) {
793  ts5_fatal("%s: %s\n", "ts5_get_sample_status",
794  "memory streams not implemented yet");
795  }
796  else {
797  ts5_fatal("ts5_get_sample_status: sample type unknown\n");
798  }
799 
800  return retval;
801 }
802 
803 
804 ////////////////////////////////////////////////////////////////////////////////
805 //@}
806 ////////////////////////////////////////////////////////////////////////////////
807 
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// @name Manipulating sample data
811 /// The data of a sample can be accessed
812 /// with the ts5_get_sample_data_pointer() function.
813 ///
814 /// This way, the user can generate simple sounds such as sine waves,
815 /// white noise, etc.
816 ///
817 /// The process is as follows:
818 /// - Allocate a sample
819 /// - Get acces to the sample data
820 /// - Manipulate the sample data
821 /// - Play the sample
822 ///
823 /// See <a href="audio02_8c-example.html">audio02.c</a>
824 /// for an example that shows how this works.
825 //@{
826 ////////////////////////////////////////////////////////////////////////////////
827 
828 
829 ////////////////////////////////////////////////////////////////////////////////
830 /// Get acces to a sample's data.
831 ///
832 /// \param sample Pointer to the sample that will queried.
833 ///
834 /// \return a pointer to the sample data.
835 ////////////////////////////////////////////////////////////////////////////////
836 void *ts5_get_sample_data_pointer(TS5_SAMPLE *sample)
837 {
838  ts5_check_audio("ts5_get_sample_data_pointer");
839  ts5_log(TS5_LOGLEVEL_5, "ts5_get_sample_data_pointer(%p)\n", sample);
840 
841  if (!sample) {
842  ts5_fatal("ts5_get_sample_data_pointer: sample pointer is null\n");
843  }
844 
845  void *retval;
846  retval = NULL;
847 
848  if (sample->issample) {
849  retval = al_get_sample_data(sample->sample);
850  }
851  else if (sample->isfilestream) {
852  ts5_fatal("ts5_get_sample_data_pointer: file streams not implemented yet\n");
853  }
854  else if (sample->ismemorystream) {
855  ts5_fatal("ts5_get_sample_data_pointer: memory streams not implemented yet\n");
856  }
857 
858  return retval;
859 }
860 
861 
862 ////////////////////////////////////////////////////////////////////////////////
863 //@}
864 ////////////////////////////////////////////////////////////////////////////////
865 
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// @name Recording samples
869 /// Audio samples can be recorded using the functions below.
870 ///
871 /// The user must explicilty start the recording system by
872 /// calling ts5_start_audio_recorder().
873 ///
874 /// During long breaks in the program (not intertrial intervals)
875 /// the user can stop the audio recorder to save resources,
876 /// then start the recorder again when the program continues.
877 ///
878 /// Recording is a two-step process:
879 /// - A call to ts5_record_sample() starts the recording of a sample.
880 /// This generates a timestamp and then
881 /// waits for the first fragment of audio from the driver.
882 /// The part of the fragment that is older than the timestamp is discarded.
883 /// The remainder is stored in the sample.
884 /// - Once the recording is started the user needs to repeatedly call
885 /// ts5_get_sample_fragments() to append the available audio fragments
886 /// to the sample.
887 /// The audio buffer is about 10 seconds, so the recording
888 /// loop does not need to be too tight.
889 ///
890 /// See <a href="audio03_8c-example.html">audio03.c</a>
891 /// for an example that shows how this works.
892 //@{
893 ////////////////////////////////////////////////////////////////////////////////
894 
895 
896 ////////////////////////////////////////////////////////////////////////////////
897 /// Start the audio recorder.
898 ///
899 /// This function has to be called explicitly by the user
900 /// before samples can be recorded.
901 ////////////////////////////////////////////////////////////////////////////////
903 {
904  ts5_check_audio_recorder("ts5_start_audio_recorder");
905  if (!al_start_audio_recorder(_ts5_data.audio.recorder)) {
906  ts5_fatal("ts5_start_audio_recorder: could not start audio recorder\n");
907  }
909 }
910 
911 
912 ////////////////////////////////////////////////////////////////////////////////
913 /// Stop the audio recorder.
914 ///
915 /// This function has to be called explicitly by the user
916 /// at the end of the program.
917 ////////////////////////////////////////////////////////////////////////////////
919 {
920  ts5_check_audio_recorder("ts5_stop_audio_recorder");
922  al_stop_audio_recorder(_ts5_data.audio.recorder);
925  }
926 }
927 
928 
929 ////////////////////////////////////////////////////////////////////////////////
930 /// Flush the audio recorder buffer.
931 ////////////////////////////////////////////////////////////////////////////////
933 {
934  ts5_check_audio_recorder("ts5_flush_audio_recorder");
935  al_flush_event_queue(_ts5_data.audio.recorder_queue);
936 }
937 
938 
939 ////////////////////////////////////////////////////////////////////////////////
940 /// Start recording a sample.
941 ///
942 /// \param sample Pointer to the sample that will be recorded.
943 ////////////////////////////////////////////////////////////////////////////////
944 void ts5_record_sample(TS5_SAMPLE *sample)
945 {
946  ts5_check_audio_recorder2("ts5_record_sample");
947  ts5_check_audio_recorder3("ts5_record_sample", sample);
948 
949  // get some parameters
950  sample->start_time = al_get_time();
951  int channels = ts5_get_audio_channels();
952  int depth = al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
953  double samplerate = ts5_get_audio_samplerate();
954 
955  // remove buffered audio fragments
957 
958  // set buffer pointer of the sample to the beginning
959  sample->buffer_recorder_position = sample->buffer;
960 
961  // wait for the first recorder fragment
962  ALLEGRO_EVENT event;
963  do {
964  al_wait_for_event(_ts5_data.audio.recorder_queue, &event);
965  } while(event.type != ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT);
966  ALLEGRO_AUDIO_RECORDER_EVENT *recorder_event =
967  al_get_audio_recorder_event(&event);
968 
969  // compute fragment onset and n of samples to skip
970  double fragment_onset = event.any.timestamp - recorder_event->samples / samplerate;
971  int64_t samples_to_skip = (sample->start_time - fragment_onset) * samplerate;
972 
973  if (samples_to_skip < 0) {
974  samples_to_skip = 0;
975  }
976 
977  // compute n of samples to copy
978  int64_t samples_to_copy = channels * (recorder_event->samples - samples_to_skip);
979 
980  if (samples_to_copy > sample->buffer_end - sample->buffer_recorder_position) {
981  samples_to_copy = sample->buffer_end - sample->buffer_recorder_position;
982  }
983 
984  if (samples_to_copy < 0) {
985  samples_to_copy = 0;
986  }
987 
988  // copy to the sample buffer
989  memcpy(sample->buffer_recorder_position, recorder_event->buffer + samples_to_skip * channels,
990  (uint64_t)samples_to_copy * depth);
991 
992  // update buffer counter
993  sample->buffer_recorder_position += samples_to_copy;
994 }
995 
996 
997 ////////////////////////////////////////////////////////////////////////////////
998 /// Update the sample buffer when recording.
999 ///
1000 /// \param sample Pointer to the sample that will be recorded.
1001 ///
1002 /// \return 1 if the sample is full, 0 if not.
1003 ////////////////////////////////////////////////////////////////////////////////
1004 int ts5_get_sample_fragments(TS5_SAMPLE *sample)
1005 {
1006  ts5_check_audio_recorder2("ts5_get_sample_fragments");
1007  ts5_check_audio_recorder3("ts5_get_sample_fragments", sample);
1008 
1009  if (sample->buffer_recorder_position == sample->buffer) {
1010  ts5_fatal("ts5_get_sample_fragments: audio recording not started yet\n");
1011  }
1012 
1013  int channels = ts5_get_audio_channels();
1014  int depth = al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
1015 
1016  // update until all events are processed or until the sample is full
1017  int full = 0;
1018  ALLEGRO_EVENT event;
1019  while (!full && al_get_next_event(_ts5_data.audio.recorder_queue, &event)) {
1020 
1021  if (event.type==ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT) {
1022 
1023  ALLEGRO_AUDIO_RECORDER_EVENT *recorder_event =
1024  al_get_audio_recorder_event(&event);
1025 
1026  // compute n of samples to copy
1027  int64_t samples_to_copy = channels * recorder_event->samples;
1028  if (samples_to_copy > sample->buffer_end - sample->buffer_recorder_position) {
1029  samples_to_copy = sample->buffer_end - sample->buffer_recorder_position;
1030  full = 1;
1031  }
1032 
1033  // write to the buffer
1034  memcpy(sample->buffer_recorder_position, recorder_event->buffer,
1035  (uint64_t)samples_to_copy * depth);
1036 
1037  // update buffer counter
1038  sample->buffer_recorder_position += samples_to_copy;
1039 
1040  }
1041  }
1042  return full;
1043 }
1044 
1045 
1046 ////////////////////////////////////////////////////////////////////////////////
1047 //@}
1048 ////////////////////////////////////////////////////////////////////////////////
1049 
1050 
1051 ////////////////////////////////////////////////////////////////////////////////
1052 /// @name Software voice key
1053 /// The audio recorder can be used as a software voice key.
1054 ///
1055 /// The user has to explicitly start an audio recording to start the voice key
1056 /// and update the sample buffer with ts5_get_sample_fragments().
1057 /// The ts5_detect_voice_onsets() function will then detect voice onsets
1058 /// and offsets and notify the timer functions of each onset or offset
1059 /// that is detected.
1060 ///
1061 /// See timer.c for more information about response registration.
1062 ///
1063 /// See <a href="audio04_8c-example.html">audio04.c</a>
1064 /// for an example that shows how the software voice key works.
1065 //@{
1066 ////////////////////////////////////////////////////////////////////////////////
1067 
1068 
1069 ////////////////////////////////////////////////////////////////////////////////
1070 /// Define the software voice key as a response button.
1071 ///
1072 /// \param button Number of the button (buttons are counted from 1).
1073 ///
1074 /// \return The reponse number associated with the button.
1075 ///
1076 /// Give a positive number for the button if you want to monitor button press events,
1077 /// a negative number if you want to monitor button release events.
1078 ////////////////////////////////////////////////////////////////////////////////
1080 {
1081  ts5_check_voicekey("ts5_define_voicekey_button");
1082  ts5_log(TS5_LOGLEVEL_3, "ts5_define_voicekey_button(%d)\n", button);
1083 
1084  if (abs(button)>_ts5_status.timer.voicekey.num_buttons) {
1085  ts5_fatal("%s: %s %d, %s %d is %d\n", "ts5_define_voicekey_button",
1086  "button argument is", button,
1087  "number of voicekey buttons",
1088  _ts5_status.timer.voicekey.num_buttons);
1089  }
1090 
1091  if (button>0 && _ts5_status.timer.voicekey
1092  .button_press_defined[button-1]!=0) {
1093  ts5_fatal("%s: %s %d %s\n", "ts5_define_voicekey_button",
1094  "button press", button, "is already defined");
1095  }
1096 
1097  if (button<0 && _ts5_status.timer.voicekey
1098  .button_release_defined[-button-1]!=0) {
1099  ts5_fatal("%s: %s %d %s\n", "ts5_define_voicekey_button",
1100  "button release", button, "is already defined");
1101  }
1102 
1103  _ts5_status.timer.voicekey_is_response_device = 1;
1104  _ts5_status.timer.num_defined_buttons++;
1105  _ts5_status.timer.num_active_buttons++;
1106  _ts5_status.timer.voicekey.num_defined_buttons++;
1107  _ts5_status.timer.voicekey.num_active_buttons++;
1108 
1109  if (button>0) {
1110  _ts5_status.timer.voicekey
1111  .button_press_defined[button-1] =
1112  _ts5_status.timer.num_defined_buttons;
1113 
1114  _ts5_status.timer.voicekey
1115  .button_press_active[button-1] =
1116  _ts5_status.timer.num_defined_buttons;
1117  }
1118  else {
1119  _ts5_status.timer.voicekey
1120  .button_release_defined[-button-1] =
1121  _ts5_status.timer.num_defined_buttons;
1122 
1123  _ts5_status.timer.voicekey
1124  .button_release_active[-button-1] =
1125  _ts5_status.timer.num_defined_buttons;
1126  }
1127 
1128  return _ts5_status.timer.num_defined_buttons;
1129 }
1130 
1131 
1132 ////////////////////////////////////////////////////////////////////////////////
1133 /// Detect voice onsets in a sample.
1134 ///
1135 /// \param sample Pointer to the sample that will be processed.
1136 ////////////////////////////////////////////////////////////////////////////////
1137 void ts5_detect_voice_onsets(TS5_SAMPLE *sample)
1138 {
1139  ts5_check_audio_recorder2("ts5_detect_voice_onsets");
1140  ts5_check_audio_recorder3("ts5_detect_voice_onsets", sample);
1141  ts5_check_voicekey("ts5_detect_voice_onsets");
1142  ts5_log(TS5_LOGLEVEL_4, "ts5_detect_voice_onsets(%p)\n", sample);
1143 
1144  int channels = ts5_get_sample_channels(sample);
1145  int samplerate = al_get_sample_frequency(sample->sample);
1146 
1147  int64_t sample_idx;
1148  int64_t start_sample =
1149  sample->buffer_voicekey_position - sample->buffer;
1150 
1151  int64_t stop_sample =
1152  sample->buffer_recorder_position - sample->buffer;
1153 
1154  int64_t slice_idx;
1155  int64_t start_slice = start_sample * 1000 / samplerate / channels;
1156  int64_t stop_slice = stop_sample * 1000 / samplerate / channels;
1157 
1158  // voicekey step 1: compute sum of squares per slice
1159  for(sample_idx = start_sample; sample_idx < stop_sample; sample_idx++) {
1160 
1161  slice_idx = sample_idx * 1000 / samplerate / channels;
1162  sample->voicekey_num_samples[slice_idx]++;
1163  sample->voicekey[slice_idx] +=
1164  (sample->buffer[sample_idx] * sample->buffer[sample_idx]);
1165  }
1166 
1167  // voicekey step 2: take root mean square per slice
1168  int max = 32767; // maximum value of 16-bit integers
1169  for(slice_idx = start_slice; slice_idx < stop_slice; slice_idx++) {
1170  sample->voicekey[slice_idx] =
1171  sqrt(sample->voicekey[slice_idx]/sample->voicekey_num_samples[slice_idx]) / max;
1172  }
1173 
1174  // voicekey step 3: treshold
1175  for(slice_idx = start_slice; slice_idx < stop_slice; slice_idx++) {
1176 
1177  if(sample->voicekey[slice_idx] > _ts5_status.timer.voicekey.treshold) {
1178  sample->voicekey[slice_idx] = 1.0;
1179  }
1180  else {
1181  sample->voicekey[slice_idx] = 0.0;
1182  }
1183  }
1184 
1185  // step 4: detect state changes
1186  int current_state;
1187 
1188  for(slice_idx = start_slice; slice_idx < stop_slice; slice_idx++) {
1189 
1190  if(sample->voicekey[slice_idx] > _ts5_status.timer.voicekey.treshold) {
1191  current_state = 1;
1192  }
1193  else {
1194  current_state = 0;
1195  }
1196 
1197  if(current_state != sample->previous_state) {
1198 
1199  int64_t diff = slice_idx - sample->last_state_toggle_time;
1200  int rise = current_state && diff > _ts5_status.timer.voicekey.rise_delay * 1000;
1201  int drop = (!current_state) && diff > _ts5_status.timer.voicekey.drop_delay * 1000;
1202 
1203  if(rise || drop) {
1204 
1205  ALLEGRO_EVENT voicekey_event;
1206  if (rise) {
1207  voicekey_event.user.type = TS5_EVENT_VOICEKEY_BUTTON_DOWN;
1208  }
1209 
1210  if (drop) {
1211  voicekey_event.user.type = TS5_EVENT_VOICEKEY_BUTTON_UP;
1212  }
1213 
1214  voicekey_event.user.data1 = 1;
1215  voicekey_event.user.data2 = 1;
1216 
1217  // make our own timestamp: time where onset/offset is detected
1218  // allegro timestamp: time where event is emitted
1219  voicekey_event.user.data3 =
1220  (intptr_t)(slice_idx*1000 + sample->start_time*1000000.0);
1221 
1222  sample->previous_state = current_state;
1223  sample->last_state_toggle_time = slice_idx;
1224 
1225  al_emit_user_event(
1226  &_ts5_data.timer.voicekey_response_event_source,
1227  &voicekey_event, NULL);
1228  }
1229  }
1230  }
1231 }
1232 
1233 
1234 ////////////////////////////////////////////////////////////////////////////////
1235 /// Set the voice key treshold.
1236 ///
1237 /// \param treshold Treshold as a value beteen 0.0 (silence) and 1.0 (max).
1238 /// \return The previous setting.
1239 ///
1240 /// The default treshold is set to 0.5.
1241 ////////////////////////////////////////////////////////////////////////////////
1242 double ts5_set_voicekey_treshold(double treshold)
1243 {
1244  ts5_check_voicekey("ts5_set_voicekey_treshold");
1245  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_treshold(%f)\n", treshold);
1246 
1247  if (treshold < 0.0) {
1248  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_treshold",
1249  "treshold should be positive", treshold);
1250  }
1251 
1252  if (treshold > 1.0) {
1253  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_treshold",
1254  "treshold should be smaller than 1.0", treshold);
1255  }
1256 
1257  double retval =
1258  _ts5_status.timer.voicekey.treshold;
1259 
1260  _ts5_status.timer.voicekey.treshold = treshold;
1261 
1262  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1263  "ts5_set_voicekey_treshold",
1264  "set voice key treshold",
1265  _ts5_status.timer.voicekey.treshold,
1266  retval);
1267 
1268  return retval;
1269 }
1270 
1271 
1272 ////////////////////////////////////////////////////////////////////////////////
1273 /// Get the voice key treshold.
1274 ///
1275 /// \return The voice key treshold.
1276 ////////////////////////////////////////////////////////////////////////////////
1278 {
1279  ts5_check_voicekey("ts5_get_voicekey_treshold");
1280  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_treshold\n");
1281 
1282  return _ts5_status.timer.voicekey.treshold;
1283 }
1284 
1285 
1286 ////////////////////////////////////////////////////////////////////////////////
1287 /// Set the voice key rise delay.
1288 ///
1289 /// \param rise_delay Rise delay in seconds.
1290 /// \return The previous setting.
1291 ///
1292 /// The default rise delay is set to 0.2 seconds.
1293 ////////////////////////////////////////////////////////////////////////////////
1294 double ts5_set_voicekey_rise_delay(double rise_delay)
1295 {
1296  ts5_check_voicekey("ts5_set_voicekey_rise_delay");
1297  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_rise_delay(%f)\n", rise_delay);
1298 
1299  if (rise_delay < 0.0) {
1300  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_rise_delay",
1301  "rise_delay should be positive", rise_delay);
1302  }
1303 
1304  double retval = _ts5_status.timer.voicekey.rise_delay;
1305 
1306  _ts5_status.timer.voicekey.rise_delay = rise_delay;
1307 
1308  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1309  "ts5_set_voicekey_rise_delay",
1310  "set voice key rise_delay",
1311  _ts5_status.timer.voicekey.rise_delay,
1312  retval);
1313 
1314  return retval;
1315 }
1316 
1317 
1318 ////////////////////////////////////////////////////////////////////////////////
1319 /// Get the voice key rise delay.
1320 ///
1321 /// \return The voice key rise delay.
1322 ////////////////////////////////////////////////////////////////////////////////
1324 {
1325  ts5_check_voicekey("ts5_get_voicekey_rise_delay");
1326  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_rise_delay\n");
1327 
1328  return _ts5_status.timer.voicekey.rise_delay;
1329 }
1330 
1331 
1332 
1333 ////////////////////////////////////////////////////////////////////////////////
1334 /// Set the voice key drop delay.
1335 ///
1336 /// \param drop_delay Rise delay in seconds.
1337 /// \return The previous setting.
1338 ///
1339 /// The default drop delay is set to 0.2 seconds.
1340 ////////////////////////////////////////////////////////////////////////////////
1341 double ts5_set_voicekey_drop_delay(double drop_delay)
1342 {
1343  ts5_check_voicekey("ts5_set_voicekey_drop_delay");
1344  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_drop_delay(%f)\n", drop_delay);
1345 
1346  if (drop_delay < 0.0) {
1347  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_drop_delay",
1348  "drop_delay should be positive", drop_delay);
1349  }
1350 
1351  double retval = _ts5_status.timer.voicekey.drop_delay;
1352 
1353  _ts5_status.timer.voicekey.drop_delay = drop_delay;
1354 
1355  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1356  "ts5_set_voicekey_drop_delay",
1357  "set voice key drop_delay",
1358  _ts5_status.timer.voicekey.drop_delay,
1359  retval);
1360 
1361  return retval;
1362 }
1363 
1364 
1365 ////////////////////////////////////////////////////////////////////////////////
1366 /// Get the voice key drop delay.
1367 ///
1368 /// \return The voice key drop delay.
1369 ////////////////////////////////////////////////////////////////////////////////
1371 {
1372  ts5_check_voicekey("ts5_get_voicekey_drop_delay");
1373  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_drop_delay\n");
1374 
1375  return _ts5_status.timer.voicekey.drop_delay;
1376 }
1377 
1378 
1379 ////////////////////////////////////////////////////////////////////////////////
1380 //@}
1381 ////////////////////////////////////////////////////////////////////////////////
1382 
1383 
1384 
1385 ////////////////////////////////////////////////////////////////////////////////
1386 /// @name Sample parameters
1387 /// For each sample the parameters can be queried/set using the functions below:
1388 ///
1389 /// - Sample position, speed, gain, pan and playmode
1390 /// can be adjusted at any time, even when the sample is playing.
1391 /// - Samplerate, channels, depth and length are defined when the
1392 /// sample is read or allocated.
1393 ///
1394 //@{
1395 ////////////////////////////////////////////////////////////////////////////////
1396 
1397 
1398 ////////////////////////////////////////////////////////////////////////////////
1399 /// Get the sample rate of a sample.
1400 ///
1401 /// \param sample Pointer to the sample that will queried.
1402 ///
1403 /// \return The sample rate of the sample.
1404 ////////////////////////////////////////////////////////////////////////////////
1405 unsigned int ts5_get_sample_samplerate(TS5_SAMPLE *sample)
1406 {
1407  ts5_check_audio("ts5_get_sample_samplerate");
1408  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_samplerate(%p)\n", sample);
1409 
1410  if (!sample) {
1411  ts5_fatal("ts5_get_sample_samplerate: sample pointer is null\n");
1412  }
1413 
1414  unsigned int retval = 0;
1415 
1416  if (sample->issample) {
1417  retval = al_get_sample_frequency(sample->sample);
1418  }
1419  else if (sample->isfilestream) {
1420  retval = al_get_audio_stream_frequency(sample->stream);
1421  }
1422  else if (sample->ismemorystream) {
1423  ts5_fatal("%s: %s\n", "ts5_get_sample_samplerate",
1424  "memory streams not implemented yet");
1425  }
1426 
1427  return retval;
1428 }
1429 
1430 
1431 ////////////////////////////////////////////////////////////////////////////////
1432 /// Get the number of channels of a sample.
1433 ///
1434 /// \param sample Pointer to the sample that will queried.
1435 ///
1436 /// \return The number of channels of the sample.
1437 ////////////////////////////////////////////////////////////////////////////////
1438 unsigned int ts5_get_sample_channels(TS5_SAMPLE *sample)
1439 {
1440  ts5_check_audio("ts5_get_sample_channels");
1441  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_channels(%p)\n", sample);
1442 
1443  if (!sample) {
1444  ts5_fatal("ts5_get_sample_channels: sample pointer is null\n");
1445  }
1446 
1447  ALLEGRO_CHANNEL_CONF channels = 0;
1448 
1449  if (sample->issample) {
1450  channels = al_get_sample_channels(sample->sample);
1451  }
1452  else if (sample->isfilestream) {
1453  channels = al_get_audio_stream_channels(sample->stream);
1454  }
1455  else if (sample->ismemorystream) {
1456  ts5_fatal("%s: %s\n", "ts5_get_sample_channels",
1457  "memory streams not implemented yet");
1458  }
1459 
1460  unsigned int retval = 0;
1461 
1462  if (channels == ALLEGRO_CHANNEL_CONF_1) {
1463  retval = TS5_MONO;
1464  }
1465  else if (channels == ALLEGRO_CHANNEL_CONF_2) {
1466  retval = TS5_STEREO;
1467  }
1468  else {
1469  ts5_fatal("%s: %s\n", "ts5_get_sample_channels",
1470  "got an unknown number of channels");
1471  }
1472 
1473  return retval;
1474 }
1475 
1476 
1477 ////////////////////////////////////////////////////////////////////////////////
1478 /// Get the sample depth of a sample.
1479 ///
1480 /// \param sample Pointer to the sample that will queried.
1481 ///
1482 /// \return The sample depth of a sample.
1483 ////////////////////////////////////////////////////////////////////////////////
1484 int ts5_get_sample_depth(TS5_SAMPLE *sample)
1485 {
1486  ts5_check_audio("ts5_get_sample_depth");
1487  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_depth(%p)\n", sample);
1488 
1489  if (!sample) {
1490  ts5_fatal("ts5_get_sample_depth: sample pointer is null\n");
1491  }
1492 
1493  ALLEGRO_AUDIO_DEPTH depth = 0;
1494 
1495  if (sample->issample) {
1496  depth = al_get_sample_depth(sample->sample);
1497  }
1498  else if (sample->isfilestream) {
1499  depth = al_get_audio_stream_depth(sample->stream);
1500  }
1501  else if (sample->ismemorystream) {
1502  ts5_fatal("ts5_get_sample_depth: memory streams not implemented yet\n");
1503  }
1504 
1505  int retval = 0;
1506 
1507  if (depth == ALLEGRO_AUDIO_DEPTH_INT16) {
1508  retval = TS5_INTEGER;
1509  }
1510  else if (depth == ALLEGRO_AUDIO_DEPTH_FLOAT32) {
1511  retval = TS5_FLOAT;
1512  }
1513  else {
1514  ts5_fatal("ts5_get_audio_depth: got an unknown sample depth\n");
1515  }
1516 
1517  return retval;
1518 }
1519 
1520 
1521 ////////////////////////////////////////////////////////////////////////////////
1522 /// Get the length of a sample.
1523 ///
1524 /// \param sample Pointer to the sample that will queried.
1525 ///
1526 /// \return The length of the sample.
1527 ////////////////////////////////////////////////////////////////////////////////
1528 double ts5_get_sample_length(TS5_SAMPLE *sample)
1529 {
1530  ts5_check_audio("ts5_get_sample_length");
1531  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_length(%p)\n", sample);
1532 
1533  if (!sample) {
1534  ts5_fatal("ts5_get_sample_length: sample pointer is null\n");
1535  }
1536 
1537  double retval = 0.0;
1538 
1539  if (sample->issample) {
1540  double freq = al_get_sample_frequency(sample->sample);
1541  retval = (double)al_get_sample_length(sample->sample) / freq;
1542  }
1543  else if (sample->isfilestream) {
1544  retval = al_get_audio_stream_length_secs(sample->stream);
1545  }
1546  else if (sample->ismemorystream) {
1547  ts5_fatal("%s: %s\n", "ts5_get_sample_length",
1548  "memory streams not implemented yet");
1549  }
1550 
1551  return retval;
1552 }
1553 
1554 
1555 ////////////////////////////////////////////////////////////////////////////////
1556 /// Set the playback position of a sample.
1557 ///
1558 /// \param sample Pointer to the sample that will be adjusted.
1559 /// \param position The new playback position.
1560 ///
1561 /// \return The old playback position.
1562 ////////////////////////////////////////////////////////////////////////////////
1563 double ts5_set_sample_position(TS5_SAMPLE *sample, double position)
1564 {
1565  ts5_check_audio("ts5_set_sample_position");
1566 
1567  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_position(%p,%u)\n",
1568  sample, position);
1569 
1570  if (!sample) {
1571  ts5_fatal("ts5_set_sample_position: sample pointer is null\n");
1572  }
1573 
1574  double retval = 0.0;
1575 
1576  if (sample->issample) {
1577 
1578  double freq = al_get_sample_frequency(sample->sample);
1579  double max = al_get_sample_length(sample->sample) / freq;
1580 
1581  if (position > max) {
1582  ts5_fatal("ts5_set_sample_position: position should be",
1583  " <= the length of the sample (%f)\n", max);
1584  }
1585 
1586  retval = al_get_sample_instance_position(sample->instance) / freq;
1587 
1588  if (!(al_set_sample_instance_position(sample->instance, position*freq))) {
1589  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1590  "could not change sample position");
1591  }
1592  }
1593  else if (sample->isfilestream) {
1594 
1595  unsigned int max = al_get_audio_stream_length_secs(sample->stream);
1596 
1597  if (position > max) {
1598  ts5_fatal("ts5_set_sample_position: position should be",
1599  " <= the length of the sample (%f)\n", max);
1600  }
1601 
1602  retval = al_get_audio_stream_position_secs(sample->stream);
1603 
1604  if (!(al_seek_audio_stream_secs(sample->stream, position))) {
1605  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1606  "could not change sample position");
1607  }
1608  }
1609  else if (sample->ismemorystream) {
1610  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1611  "memory streams not implemented yet");
1612  }
1613 
1614  return retval;
1615 }
1616 
1617 
1618 ////////////////////////////////////////////////////////////////////////////////
1619 /// Get the playback position of a sample.
1620 ///
1621 /// \param sample Pointer to the sample that will be queried.
1622 ///
1623 /// \return The current playback position.
1624 ////////////////////////////////////////////////////////////////////////////////
1625 double ts5_get_sample_position(TS5_SAMPLE *sample)
1626 {
1627  ts5_check_audio("ts5_get_sample_position");
1628  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_position(%p)\n", sample);
1629 
1630  if (!sample) {
1631  ts5_fatal("ts5_get_sample_length: sample pointer is null\n");
1632  }
1633 
1634  double retval = 0.0;
1635 
1636  if (sample->issample) {
1637  double freq = al_get_sample_frequency(sample->sample);
1638  retval = al_get_sample_instance_position(sample->instance) / freq;
1639  }
1640  else if (sample->isfilestream) {
1641  retval = al_get_audio_stream_position_secs(sample->stream);
1642  }
1643  else if (sample->ismemorystream) {
1644  ts5_fatal("%s: %s\n", "ts5_get_sample_position",
1645  "memory streams not implemented yet");
1646  }
1647 
1648  return retval;
1649 }
1650 
1651 
1652 ////////////////////////////////////////////////////////////////////////////////
1653 /// Set the playback speed of a sample.
1654 ///
1655 /// \param sample Pointer to the sample that will be adjusted.
1656 /// \param speed The new playback speed (1.0 is normal speed).
1657 ///
1658 /// \return The old playback speed.
1659 ////////////////////////////////////////////////////////////////////////////////
1660 double ts5_set_sample_speed(TS5_SAMPLE *sample, double speed)
1661 {
1662  ts5_check_audio("ts5_set_sample_speed");
1663  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_speed(%p,%f)\n", sample, speed);
1664 
1665  if (!sample) {
1666  ts5_fatal("ts5_set_sample_speed: sample pointer is null\n");
1667  }
1668 
1669  if (speed < 0) {
1670  ts5_fatal("ts5_set_sample_speed: speed should be >0 (is %f)\n", speed);
1671  }
1672 
1673  double retval = 0.0;
1674 
1675  if (sample->issample) {
1676 
1677  retval = al_get_sample_instance_speed(sample->instance);
1678 
1679  if (!(al_set_sample_instance_speed(sample->instance, speed))) {
1680  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_speed",
1681  "could not change sample speed", speed);
1682  }
1683  }
1684  else if (sample->isfilestream) {
1685 
1686  retval = al_get_audio_stream_speed(sample->stream);
1687 
1688  if (!(al_set_audio_stream_speed(sample->stream, speed))) {
1689  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_speed",
1690  "could not change sample speed", speed);
1691  }
1692  }
1693  else if (sample->ismemorystream) {
1694  ts5_fatal("%s: %s\n", "ts5_set_sample_speed",
1695  "memory streams not implemented yet");
1696  }
1697 
1698  return retval;
1699 }
1700 
1701 
1702 ////////////////////////////////////////////////////////////////////////////////
1703 /// Get the playback speed of a sample.
1704 ///
1705 /// \param sample Pointer to the sample that will be queried.
1706 ///
1707 /// \return The current playback speed.
1708 ////////////////////////////////////////////////////////////////////////////////
1709 double ts5_get_sample_speed(TS5_SAMPLE *sample)
1710 {
1711  ts5_check_audio("ts5_get_sample_speed");
1712  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_speed(%p)\n", sample);
1713 
1714  if (!sample) {
1715  ts5_fatal("ts5_get_sample_speed: sample pointer is null\n");
1716  }
1717 
1718  double retval = 0.0;
1719 
1720  if (sample->issample) {
1721  retval = al_get_sample_instance_speed(sample->instance);
1722  }
1723  else if (sample->isfilestream) {
1724  retval = al_get_audio_stream_speed(sample->stream);
1725  }
1726  else if (sample->ismemorystream) {
1727  ts5_fatal("ts5_get_sample_speed: memory streams not implemented yet\n");
1728  }
1729 
1730  return retval;
1731 }
1732 
1733 
1734 ////////////////////////////////////////////////////////////////////////////////
1735 /// Set the playback gain of a sample.
1736 ///
1737 /// \param sample Pointer to the sample that will be adjusted.
1738 /// \param gain The new playback gain (1.0 is normal gain).
1739 ///
1740 /// \return The old gain setting.
1741 ////////////////////////////////////////////////////////////////////////////////
1742 double ts5_set_sample_gain(TS5_SAMPLE *sample, double gain)
1743 {
1744  ts5_check_audio("ts5_set_sample_gain");
1745  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_gain(%p,%f)\n", sample, gain);
1746 
1747  if (!sample) {
1748  ts5_fatal("ts5_set_sample_gain: sample pointer is null\n");
1749  }
1750 
1751  if (gain < 0) {
1752  ts5_fatal("ts5_set_sample_gain: gain should be >0 (is %f)\n", gain);
1753  }
1754 
1755  double retval = 0.0;
1756 
1757  if (sample->issample) {
1758 
1759  retval = al_get_sample_instance_gain(sample->instance);
1760 
1761  if (!(al_set_sample_instance_gain(sample->instance, gain))) {
1762  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_gain",
1763  "could not change sample gain", gain);
1764  }
1765  }
1766  else if (sample->isfilestream) {
1767 
1768  retval = al_get_audio_stream_gain(sample->stream);
1769 
1770  if (!(al_set_audio_stream_gain(sample->stream, gain))) {
1771  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_gain",
1772  "could not change sample gain", gain);
1773  }
1774  }
1775  else if (sample->ismemorystream) {
1776  ts5_fatal("ts5_set_sample_gain: memory streams not implemented yet\n");
1777  }
1778 
1779  return retval;
1780 }
1781 
1782 
1783 ////////////////////////////////////////////////////////////////////////////////
1784 /// Get the playback gain of a sample.
1785 ///
1786 /// \param sample Pointer to the sample that will be queried.
1787 ///
1788 /// \return The current playback gain.
1789 ////////////////////////////////////////////////////////////////////////////////
1790 double ts5_get_sample_gain(TS5_SAMPLE *sample)
1791 {
1792  ts5_check_audio("ts5_get_sample_gain");
1793  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_gain(%p)\n", sample);
1794 
1795  if (!sample) {
1796  ts5_fatal("ts5_get_sample_gain: sample pointer is null\n");
1797  }
1798 
1799  double retval = 0.0;
1800 
1801  if (sample->issample) {
1802  retval = al_get_sample_instance_gain(sample->instance);
1803  }
1804  else if (sample->isfilestream) {
1805  retval = al_get_audio_stream_gain(sample->stream);
1806  }
1807  else if (sample->ismemorystream) {
1808  ts5_fatal("ts5_get_sample_gain: memory streams not implemented yet\n");
1809  }
1810 
1811  return retval;
1812 }
1813 
1814 
1815 ////////////////////////////////////////////////////////////////////////////////
1816 /// Set the playback pan of a sample.
1817 ///
1818 /// \param sample Pointer to the sample that will be adjusted.
1819 /// \param pan The new playback pan
1820 /// (-1.0 is left, 0.0 is normal, 1.0 is right).
1821 ///
1822 /// \return The old playback pan.
1823 ////////////////////////////////////////////////////////////////////////////////
1824 double ts5_set_sample_pan(TS5_SAMPLE *sample, double pan)
1825 {
1826  ts5_check_audio("ts5_set_sample_pan");
1827  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_pan(%p,%f)\n", sample, pan);
1828 
1829  if (!sample) {
1830  ts5_fatal("ts5_set_sample_pan: sample pointer is null\n");
1831  }
1832 
1833  if (pan < -1.0 || pan > 1) {
1834  ts5_fatal("%s: %s (is %f)\n", "ts5_set_sample_pan",
1835  "pan should be between -1.0 and 1.0", pan);
1836  }
1837 
1838  double retval = 0.0;
1839 
1840  if (sample->issample) {
1841 
1842  retval = al_get_sample_instance_pan(sample->instance);
1843 
1844  if (!(al_set_sample_instance_pan(sample->instance, pan))) {
1845  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_pan",
1846  "could not change sample pan", pan);
1847  }
1848  }
1849  else if (sample->isfilestream) {
1850 
1851  retval = al_get_audio_stream_pan(sample->stream);
1852 
1853  if (!(al_set_audio_stream_pan(sample->stream, pan))) {
1854  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_pan",
1855  "could not change sample pan", pan);
1856  }
1857  }
1858  else if (sample->ismemorystream) {
1859  ts5_fatal("ts5_set_sample_pan: memory streams not implemented yet\n");
1860  }
1861 
1862  return retval;
1863 }
1864 
1865 
1866 ////////////////////////////////////////////////////////////////////////////////
1867 /// Get the playback pan of a sample.
1868 ///
1869 /// \param sample Pointer to the sample that will be queried.
1870 ///
1871 /// \return The current playback pan.
1872 ////////////////////////////////////////////////////////////////////////////////
1873 double ts5_get_sample_pan(TS5_SAMPLE *sample)
1874 {
1875  ts5_check_audio("ts5_get_sample_pan");
1876  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_pan(%p)\n", sample);
1877 
1878  if (!sample) {
1879  ts5_fatal("ts5_get_sample_pan: sample pointer is null\n");
1880  }
1881 
1882  double retval = 0.0;
1883 
1884  if (sample->issample) {
1885  retval = al_get_sample_instance_pan(sample->instance);
1886  }
1887  else if (sample->isfilestream) {
1888  retval = al_get_audio_stream_pan(sample->stream);
1889  }
1890  else if (sample->ismemorystream) {
1891  ts5_fatal("memory streams not implemented yet\n");
1892  }
1893 
1894  return retval;
1895 }
1896 
1897 
1898 ////////////////////////////////////////////////////////////////////////////////
1899 /// Set the playmode of a sample.
1900 ///
1901 /// \param sample Pointer to the sample that will be adjusted.
1902 /// \param playmode The new playmode. Can be TS5_PLAY_ONCE or TS5_PLAY_LOOP.
1903 ///
1904 /// \return The old playmode.
1905 ////////////////////////////////////////////////////////////////////////////////
1906 int ts5_set_sample_playmode(TS5_SAMPLE *sample, int playmode)
1907 {
1908  ts5_check_audio("ts5_set_sample_playmode");
1909  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_playmode(%p,%d)\n",
1910  sample, playmode);
1911 
1912  if (!sample) {
1913  ts5_fatal("ts5_set_sample_playmode: sample pointer is null\n");
1914  }
1915 
1916  if (playmode != TS5_PLAY_ONCE && playmode != TS5_PLAY_LOOP) {
1917  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1918  "playmode should be TS5_PLAY_ONCE or TS5_PLAY_LOOP");
1919  }
1920 
1921  int retval = 0;
1922 
1923  if (sample->issample) {
1924 
1925  retval = al_get_sample_instance_playmode(sample->instance);
1926 
1927  if (!(al_set_sample_instance_playmode(sample->instance, playmode))) {
1928  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1929  "could not change sample playmode");
1930  }
1931  }
1932  else if (sample->isfilestream) {
1933 
1934  retval = al_get_audio_stream_playmode(sample->stream) - 3;
1935 
1936  if (!(al_set_audio_stream_playmode(sample->stream, playmode))) {
1937  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1938  "could not change sample playmode");
1939  }
1940  }
1941  else if (sample->ismemorystream) {
1942  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1943  "memory streams not implemented yet");
1944  }
1945 
1946  return retval;
1947 }
1948 
1949 
1950 ////////////////////////////////////////////////////////////////////////////////
1951 /// Get the playmode of a sample.
1952 ///
1953 /// \param sample Pointer to the sample that will be queried.
1954 ///
1955 /// \return The current playmode.
1956 ////////////////////////////////////////////////////////////////////////////////
1957 int ts5_get_sample_playmode(TS5_SAMPLE *sample)
1958 {
1959  ts5_check_audio("ts5_get_sample_playmode");
1960  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_playmode(%p)\n", sample);
1961 
1962  if (!sample) {
1963  ts5_fatal("ts5_get_sample_playmode: sample pointer is null\n");
1964  }
1965 
1966  int retval = 0;
1967 
1968  if (sample->issample) {
1969  retval = al_get_sample_instance_playmode(sample->instance);
1970  }
1971  else if (sample->isfilestream) {
1972  retval = al_get_audio_stream_playmode(sample->stream) - 3;
1973  }
1974  else if (sample->ismemorystream) {
1975  ts5_fatal("%s: %s\n", "ts5_get_sample_playmode",
1976  "memory streams not implemented yet");
1977  }
1978 
1979  return retval;
1980 }
1981 
1982 
1983 ////////////////////////////////////////////////////////////////////////////////
1984 //@}
1985 ////////////////////////////////////////////////////////////////////////////////
1986 
unsigned int ts5_get_audio_channels()
Get the number of channels of the audio system.
Definition: audio.c:155
int ts5_get_sample_playmode(TS5_SAMPLE *sample)
Get the playmode of a sample.
Definition: audio.c:1957
void ts5_record_sample(TS5_SAMPLE *sample)
Start recording a sample.
Definition: audio.c:944
int _ts5_is_tscope5_installed
Is Tscope5 installed?
double ts5_set_voicekey_rise_delay(double rise_delay)
Set the voice key rise delay.
Definition: audio.c:1294
void ts5_flush_audio_recorder()
Flush the audio recorder buffer.
Definition: audio.c:932
double ts5_get_sample_speed(TS5_SAMPLE *sample)
Get the playback speed of a sample.
Definition: audio.c:1709
void ts5_write_sample(const char *file, TS5_SAMPLE *sample)
Write a sample.
Definition: audio.c:599
unsigned int ts5_get_sample_channels(TS5_SAMPLE *sample)
Get the number of channels of a sample.
Definition: audio.c:1438
void ts5_detect_voice_onsets(TS5_SAMPLE *sample)
Detect voice onsets in a sample.
Definition: audio.c:1137
double ts5_get_voicekey_treshold()
Get the voice key treshold.
Definition: audio.c:1277
double ts5_set_sample_speed(TS5_SAMPLE *sample, double speed)
Set the playback speed of a sample.
Definition: audio.c:1660
unsigned int ts5_set_audio_samplerate(unsigned int samplerate)
Set the requested samplerate for the audio system.
Definition: audio.c:64
int _ts5_is_audio_recorder_recording
Is the audio recorder recording?
int ts5_get_sample_fragments(TS5_SAMPLE *sample)
Update the sample buffer when recording.
Definition: audio.c:1004
double ts5_get_voicekey_drop_delay()
Get the voice key drop delay.
Definition: audio.c:1370
unsigned int ts5_get_sample_samplerate(TS5_SAMPLE *sample)
Get the sample rate of a sample.
Definition: audio.c:1405
void * ts5_get_sample_data_pointer(TS5_SAMPLE *sample)
Get acces to a sample's data.
Definition: audio.c:836
void ts5_stop_audio_recorder()
Stop the audio recorder.
Definition: audio.c:918
void ts5_check_audio_recorder(char *calling_function)
Do some checks at the start of each audio recorder function.
void ts5_start_audio_recorder()
Start the audio recorder.
Definition: audio.c:902
double ts5_get_sample_length(TS5_SAMPLE *sample)
Get the length of a sample.
Definition: audio.c:1528
double ts5_get_sample_position(TS5_SAMPLE *sample)
Get the playback position of a sample.
Definition: audio.c:1625
void ts5_log(const unsigned int level, const char *format,...)
Send info to a logging window.
Definition: system.c:45
int ts5_set_audio_depth(int depth)
Set the sample depth for the audio system.
Definition: audio.c:206
unsigned int ts5_get_audio_samplerate()
Get the sample rate of the audio system.
Definition: audio.c:93
double ts5_get_voicekey_rise_delay()
Get the voice key rise delay.
Definition: audio.c:1323
int ts5_get_sample_status(TS5_SAMPLE *sample)
Query whether a sample is playing.
Definition: audio.c:775
double ts5_get_sample_pan(TS5_SAMPLE *sample)
Get the playback pan of a sample.
Definition: audio.c:1873
double ts5_set_voicekey_treshold(double treshold)
Set the voice key treshold.
Definition: audio.c:1242
void ts5_install_tscope5(char *calling_function)
Install Tscope5.
void ts5_stop_sample(TS5_SAMPLE *sample)
Stop playing a sample.
Definition: audio.c:735
double ts5_get_sample_gain(TS5_SAMPLE *sample)
Get the playback gain of a sample.
Definition: audio.c:1790
void ts5_play_sample(TS5_SAMPLE *sample)
Start playing a sample.
Definition: audio.c:671
int ts5_set_sample_playmode(TS5_SAMPLE *sample, int playmode)
Set the playmode of a sample.
Definition: audio.c:1906
int ts5_define_voicekey_button(int button)
Define the software voice key as a response button.
Definition: audio.c:1079
void ts5_check_voicekey(char *calling_function)
Do some checks at the start of each voicekey function.
int ts5_get_sample_depth(TS5_SAMPLE *sample)
Get the sample depth of a sample.
Definition: audio.c:1484
void ts5_check_audio_recorder2(char *calling_function)
Do some checks at the start of each audio recorder function.
TS5_SAMPLE * ts5_alloc_sample(double length)
Create an empty sample.
Definition: audio.c:334
void ts5_free_sample(TS5_SAMPLE *sample)
Free the memory used by a sample.
Definition: audio.c:623
double ts5_get_audio_gain()
Get the gain of the audio system.
Definition: audio.c:293
void ts5_pause_sample(TS5_SAMPLE *sample)
Pause playing a sample.
Definition: audio.c:703
void ts5_fatal(const char *format,...)
Exit safely with an error message.
Definition: system.c:533
double ts5_set_sample_gain(TS5_SAMPLE *sample, double gain)
Set the playback gain of a sample.
Definition: audio.c:1742
void ts5_check_audio_recorder3(char *calling_function, TS5_SAMPLE *sample)
Do some checks at the start of each audio recorder function.
double ts5_set_sample_position(TS5_SAMPLE *sample, double position)
Set the playback position of a sample.
Definition: audio.c:1563
unsigned int ts5_set_audio_channels(unsigned int channels)
Set the requested number of channels for the audio system.
Definition: audio.c:124
double ts5_set_sample_pan(TS5_SAMPLE *sample, double pan)
Set the playback pan of a sample.
Definition: audio.c:1824
int ts5_get_audio_depth()
Get the sample depth of the audio system.
Definition: audio.c:235
double ts5_set_audio_gain(double gain)
Set the gain (amplification factor) of the audio system.
Definition: audio.c:261
double ts5_set_voicekey_drop_delay(double drop_delay)
Set the voice key drop delay.
Definition: audio.c:1341
void ts5_check_audio(char *calling_function)
Do some checks at the start of each audio function.
TS5_SAMPLE * ts5_read_long_sample(const char *file)
Open a long sample from a file.
Definition: audio.c:537
TS5_SAMPLE * ts5_read_sample(const char *file)
Open a sample from a file.
Definition: audio.c:440