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 
377  // create the buffer
378  sample->buffer = NULL;
379  sample->buffer = al_malloc(bytes);
380  sample->buffer_pos = sample->buffer;
381  sample->buffer_end = sample->buffer + samples * _ts5_status.audio.channels;
382  if (!sample->buffer) {
383  ts5_fatal("ts5_alloc_sample: could not allocate sample buffer\n");
384  }
385 
386 
387  // create the sample
388  sample->sample = al_create_sample(sample->buffer, samples,
389  _ts5_status.audio.samplerate,
390  ALLEGRO_AUDIO_DEPTH_INT16, channels, 1);
391 
392  if (!sample->sample) {
393  ts5_fatal("ts5_alloc_sample: could not create sample\n");
394  }
395 
396 
397  // create the sample instance
398  sample->instance = al_create_sample_instance(NULL);
399 
400  if (!sample->instance) {
401  ts5_fatal("ts5_alloc_sample: could not create sample instance\n");
402  }
403 
404  if (!al_set_sample(sample->instance, sample->sample)) {
405  ts5_fatal("%s: %s\n", "ts5_alloc_sample",
406  "could not attach sample to sample instance");
407  }
408 
409  if (!al_attach_sample_instance_to_mixer
410  (sample->instance, _ts5_data.audio.mixer)) {
411  ts5_fatal("%s: %s\n", "ts5_alloc_sample",
412  "could not attach sample instance to mixer");
413  }
414 
415  al_set_sample_instance_playing(sample->instance, 0);
416 
417 
418  // voice key
419  int ntimeslices = length * 1000;
420  sample->rms_num_samples = (int *)al_malloc(ntimeslices * sizeof(int));
421  sample->rms = (double *)al_malloc(ntimeslices * sizeof(double));
422  sample->rms_pos = sample->rms;
423  sample->rms_end = sample->rms + ntimeslices;
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_pos = NULL;
490  sample->buffer_end = NULL;
491 
492  int ntimeslices = 0;
493  sample->rms_num_samples = NULL;
494  sample->rms = NULL;
495  sample->rms_pos = NULL;
496  sample->rms_end = NULL;
497 
498  // for 16 bit samples we have access tot the sample buffer
499  // so we can run an offline voice key
500  if (al_get_sample_depth(sample->sample) == ALLEGRO_AUDIO_DEPTH_INT16) {
501 
502  sample->buffer = (int16_t *)al_get_sample_data(sample->sample);
503 
504  sample->buffer_pos = sample->buffer +
505  al_get_sample_length(sample->sample) *
506  ts5_get_sample_channels(sample);
507 
508  sample->buffer_end = sample->buffer_pos;
509 
510  ntimeslices = al_get_sample_length(sample->sample) * 1000;
511  sample->rms_num_samples = (int *)al_malloc(ntimeslices * sizeof(int));
512  sample->rms = (double *)al_malloc(ntimeslices * sizeof(double));
513  sample->rms_pos = sample->rms;
514  sample->rms_end = sample->rms + ntimeslices;
515  }
516 
517  return sample;
518 }
519 
520 
521 ////////////////////////////////////////////////////////////////////////////////
522 /// Open a long sample from a file.
523 ///
524 /// \param file Path to the sample file.
525 ///
526 /// \return A pointer to the newly created sample.
527 ///
528 /// Available sample types are: wav, flac, ogg, it, mod, s3m, xm.
529 ///
530 /// The file is read from disk as it is needed.
531 ////////////////////////////////////////////////////////////////////////////////
532 TS5_SAMPLE *ts5_read_long_sample(const char *file)
533 {
534  ts5_check_audio("ts5_read_long_sample");
535  ts5_log(TS5_LOGLEVEL_2, "ts5_read_long_sample(%s)\n", file);
536 
537  TS5_SAMPLE *sample = NULL;
538  sample = (TS5_SAMPLE *)al_malloc(sizeof(TS5_SAMPLE));
539 
540  if (!sample) {
541  ts5_fatal("ts5_read_long_sample: could not allocate sample\n");
542  }
543 
544  sample->issample = 0;
545  sample->isbuffer = 0;
546  sample->isfilestream = 1;
547  sample->ismemorystream = 0;
548 
549  sample->sample = NULL;
550  sample->instance = NULL;
551  sample->stream = NULL;
552  sample->stream = al_load_audio_stream(file, 4, 2048);
553 
554  if (!sample->stream) {
555  ts5_fatal("ts5_read_long_sample: could not read sample\n");
556  }
557 
558  if (!al_attach_audio_stream_to_mixer
559  (sample->stream, _ts5_data.audio.mixer)) {
560  ts5_fatal("%s: %s\n", "ts5_read_long_sample",
561  "could not attach sample stream to mixer");
562  }
563 
564  al_set_audio_stream_playing(sample->stream, 0);
565  al_set_audio_stream_playmode(sample->stream, ALLEGRO_PLAYMODE_ONCE);
566 
567  // no start time
568  sample->start_time = 0.0;
569 
570  // no acces to the buffer for file streams
571  sample->buffer = NULL;
572  sample->buffer_pos = NULL;
573  sample->buffer_end = NULL;
574  sample->start_time = 0.0;
575 
576  // no voice key for file streams
577  sample->rms_num_samples = NULL;
578  sample->rms = NULL;
579  sample->rms_pos = NULL;
580  sample->rms_end = NULL;
581 
582 
583  return sample;
584 }
585 
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 /// Write a sample.
589 ///
590 /// \param file Path to the sample file.
591 /// \param sample Pointer to the sample that will be written.
592 ///
593 /// Only .wav is supported. The file extension should be .wav
594 ////////////////////////////////////////////////////////////////////////////////
595 void ts5_write_sample(const char *file, TS5_SAMPLE *sample)
596 {
597  ts5_check_audio("ts5_write_sample");
598  ts5_log(TS5_LOGLEVEL_2, "ts5_write_sample(%s,%p)\n", file, sample);
599 
600  if (!sample->issample) {
601  ts5_fatal("%s: %s\n", "ts5_write_sample",
602  "writing of streams is not implemented yet\n");
603  }
604 
605  if (!al_save_sample(file, sample->sample)) {
606  ts5_fatal("ts5_write_sample: could not write sample\n");
607  }
608 }
609 
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// Free the memory used by a sample.
613 ///
614 /// \param sample Pointer to the sample that will be freed.
615 ///
616 /// This function should be called at the end of the program for
617 /// each sample allocated or read by the user.
618 ////////////////////////////////////////////////////////////////////////////////
619 void ts5_free_sample(TS5_SAMPLE *sample)
620 {
621  ts5_check_audio("ts5_free_sample");
622  ts5_log(TS5_LOGLEVEL_2, "ts5_free_sample(%p)\n", sample);
623 
624  if (sample->issample) {
625  al_set_sample(sample->instance, NULL);
626  al_destroy_sample(sample->sample);
627 
628  al_detach_sample_instance(sample->instance);
629  al_destroy_sample_instance(sample->instance);
630 
631  al_free(sample->rms_num_samples);
632  al_free(sample->rms);
633  }
634  else if (sample->isfilestream) {
635  al_detach_audio_stream(sample->stream);
636  al_destroy_audio_stream(sample->stream);
637  }
638  else if (sample->ismemorystream) {
639  ts5_fatal("ts5_free_sample: memory streams not implemented yet\n");
640  }
641 
642  al_free(sample);
643 }
644 
645 
646 ////////////////////////////////////////////////////////////////////////////////
647 //@}
648 ////////////////////////////////////////////////////////////////////////////////
649 
650 
651 ////////////////////////////////////////////////////////////////////////////////
652 /// @name Playing samples
653 /// Audio samples can be played using the functions below.
654 ///
655 /// Playing a sample will not block the flow of your program.
656 /// Once a sample starts playing the function call following
657 /// ts5_play_sample() will be executed immediately.
658 //@{
659 ////////////////////////////////////////////////////////////////////////////////
660 
661 
662 ////////////////////////////////////////////////////////////////////////////////
663 /// Start playing a sample.
664 ///
665 /// \param sample Pointer to the sample that will be played.
666 ////////////////////////////////////////////////////////////////////////////////
667 void ts5_play_sample(TS5_SAMPLE *sample)
668 {
669  ts5_check_audio("ts5_play_sample");
670  ts5_log(TS5_LOGLEVEL_5, "ts5_play_sample(%p)\n", sample);
671 
672  if (!sample) {
673  ts5_fatal("ts5_play_sample: sample pointer is null\n");
674  }
675 
676  if (sample->issample) {
677 
678  if (!al_set_sample_instance_playing(sample->instance, 1)) {
679  ts5_fatal("ts5_play_sample: could not play sample\n");
680  }
681  }
682  else if (sample->isfilestream) {
683 
684  if (!al_set_audio_stream_playing(sample->stream, 1)) {
685  ts5_fatal("ts5_play_sample: could not play sample\n");
686  }
687  }
688  else if (sample->ismemorystream) {
689  ts5_fatal("ts5_play_sample: memory streams not implemented yet\n");
690  }
691 }
692 
693 
694 ////////////////////////////////////////////////////////////////////////////////
695 /// Pause playing a sample.
696 ///
697 /// \param sample Pointer to the sample that will be paused.
698 ////////////////////////////////////////////////////////////////////////////////
699 void ts5_pause_sample(TS5_SAMPLE *sample)
700 {
701  ts5_check_audio("ts5_pause_sample");
702  ts5_log(TS5_LOGLEVEL_5, "ts5_pause_sample(%p)\n", sample);
703 
704  if (!sample) {
705  ts5_fatal("ts5_pause_sample: sample pointer is null\n");
706  }
707 
708  if (sample->issample) {
709 
710  if (!al_set_sample_instance_playing(sample->instance, 0)) {
711  ts5_fatal("ts5_pause_sample: could not pause sample\n");
712  }
713  }
714  else if (sample->isfilestream) {
715 
716  if (!al_set_audio_stream_playing(sample->stream, 0)) {
717  ts5_fatal("ts5_pause_sample: could not pause sample\n");
718  }
719  }
720  else if (sample->ismemorystream) {
721  ts5_fatal("memory streams not implemented yet\n");
722  }
723 }
724 
725 
726 ////////////////////////////////////////////////////////////////////////////////
727 /// Stop playing a sample.
728 ///
729 /// \param sample Pointer to the sample that will be stopped.
730 ////////////////////////////////////////////////////////////////////////////////
731 void ts5_stop_sample(TS5_SAMPLE *sample)
732 {
733  ts5_check_audio("ts5_stop_sample");
734  ts5_log(TS5_LOGLEVEL_5, "ts5_stop_sample(%p)\n", sample);
735 
736  if (!sample) {
737  ts5_fatal("ts5_stop_sample: sample pointer is null\n");
738  }
739 
740  if (sample->issample) {
741 
742  if (!al_set_sample_instance_playing(sample->instance, 0)) {
743  ts5_fatal("ts5_stop_sample: could not stop sample\n");
744  }
745 
746  if (!al_set_sample_instance_position(sample->instance, 0)) {
747  ts5_fatal("ts5_stop_sample: could not stop sample\n");
748  }
749  }
750  else if (sample->isfilestream) {
751 
752  al_drain_audio_stream(sample->stream);
753 
754  if (!al_rewind_audio_stream(sample->stream)) {
755  ts5_fatal("ts5_stop_sample: could not rewind sample\n");
756  }
757  }
758  else if (sample->ismemorystream) {
759  ts5_fatal("ts5_stop_sample: memory streams not implemented yet\n");
760  }
761 }
762 
763 
764 ////////////////////////////////////////////////////////////////////////////////
765 /// Query whether a sample is playing.
766 ///
767 /// \param sample Pointer to the sample that will queried.
768 ///
769 /// \return 1 if the sample is playing, 0 if not.
770 ////////////////////////////////////////////////////////////////////////////////
771 int ts5_get_sample_status(TS5_SAMPLE *sample)
772 {
773  ts5_check_audio("ts5_get_sample_status");
774  ts5_log(TS5_LOGLEVEL_5, "ts5_get_sample_status(%p)\n", sample);
775 
776  if (!sample) {
777  ts5_fatal("ts5_get_sample_status: sample pointer is null\n");
778  }
779 
780  int retval = 0;
781 
782  if (sample->issample) {
783  retval = al_get_sample_instance_playing(sample->instance);
784  }
785  else if (sample->isfilestream) {
786  retval = al_get_audio_stream_playing(sample->stream);
787  }
788  else if (sample->ismemorystream) {
789  ts5_fatal("%s: %s\n", "ts5_get_sample_status",
790  "memory streams not implemented yet");
791  }
792  else {
793  ts5_fatal("ts5_get_sample_status: sample type unknown\n");
794  }
795 
796  return retval;
797 }
798 
799 
800 ////////////////////////////////////////////////////////////////////////////////
801 //@}
802 ////////////////////////////////////////////////////////////////////////////////
803 
804 
805 ////////////////////////////////////////////////////////////////////////////////
806 /// @name Maninulating sample data
807 /// The data of a sample can be accessed
808 /// with the ts5_get_sample_data_pointer() function.
809 ///
810 /// This way, the user can generate simple sounds such as sine waves,
811 /// white noise, etc.
812 ///
813 /// The process is as follows:
814 /// - Allocate a sample
815 /// - Get acces to the sample data
816 /// - Manipulate the sample data
817 /// - Play the sample
818 ///
819 /// See audio02.c for an example that shows how this works.
820 //@{
821 ////////////////////////////////////////////////////////////////////////////////
822 
823 
824 ////////////////////////////////////////////////////////////////////////////////
825 /// Get acces to a sample's data.
826 ///
827 /// \param sample Pointer to the sample that will queried.
828 ///
829 /// \return a pointer to the sample data.
830 ////////////////////////////////////////////////////////////////////////////////
831 void *ts5_get_sample_data_pointer(TS5_SAMPLE *sample)
832 {
833  ts5_check_audio("ts5_get_sample_data_pointer");
834  ts5_log(TS5_LOGLEVEL_5, "ts5_get_sample_data_pointer(%p)\n", sample);
835 
836  if (!sample) {
837  ts5_fatal("ts5_get_sample_data_pointer: sample pointer is null\n");
838  }
839 
840  void *retval;
841  retval = NULL;
842 
843  if (sample->issample) {
844  retval = al_get_sample_data(sample->sample);
845  }
846  else if (sample->isfilestream) {
847  ts5_fatal("ts5_get_sample_data_pointer: file streams not implemented yet\n");
848  }
849  else if (sample->ismemorystream) {
850  ts5_fatal("ts5_get_sample_data_pointer: memory streams not implemented yet\n");
851  }
852 
853  return retval;
854 }
855 
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 //@}
859 ////////////////////////////////////////////////////////////////////////////////
860 
861 
862 ////////////////////////////////////////////////////////////////////////////////
863 /// @name Recording samples
864 /// Audio samples can be recorded using the functions below.
865 ///
866 /// The user must explicilty start the recording system by
867 /// calling ts5_start_audio_recorder().
868 ///
869 /// During long breaks in the program (not intertrial intervals)
870 /// the user can stop the audio recorder to save resources,
871 /// then start the recorder again when the program continues.
872 ///
873 /// Recording is a two-step process:
874 /// - A call to ts5_record_sample() starts the recording of a sample.
875 /// This generates a timestamp and then
876 /// waits for the first fragment of audio from the driver.
877 /// The part of the fragment that is older than the timestamp is discarded.
878 /// The remainder is stored in the sample.
879 /// - Once the recording is started the user needs to repeatedly call
880 /// ts5_get_sample_fragments() to append the available audio fragments
881 /// to the sample.
882 /// The audio buffer is about 10 seconds, so the recording
883 /// loop does not need to be too tight.
884 ///
885 /// See audio03.c for an example that shows how this works.
886 //@{
887 ////////////////////////////////////////////////////////////////////////////////
888 
889 
890 ////////////////////////////////////////////////////////////////////////////////
891 /// Start the audio recorder.
892 ///
893 /// This function has to be called explicitly by the user
894 /// before samples can be recorded.
895 ////////////////////////////////////////////////////////////////////////////////
897 {
898  ts5_check_audio_recorder("ts5_start_audio_recorder");
899  if (!al_start_audio_recorder(_ts5_data.audio.recorder)) {
900  ts5_fatal("ts5_start_audio_recorder: could not start audio recorder\n");
901  }
903 }
904 
905 
906 ////////////////////////////////////////////////////////////////////////////////
907 /// Stop the audio recorder.
908 ///
909 /// This function has to be called explicitly by the user
910 /// at the end of the program.
911 ////////////////////////////////////////////////////////////////////////////////
913 {
914  ts5_check_audio_recorder("ts5_stop_audio_recorder");
916  al_stop_audio_recorder(_ts5_data.audio.recorder);
919  }
920 }
921 
922 
923 ////////////////////////////////////////////////////////////////////////////////
924 /// Flush the audio recorder buffer.
925 ////////////////////////////////////////////////////////////////////////////////
927 {
928  ts5_check_audio_recorder("ts5_flush_audio_recorder");
929  al_flush_event_queue(_ts5_data.audio.recorder_queue);
930 }
931 
932 
933 ////////////////////////////////////////////////////////////////////////////////
934 /// Start recording a sample.
935 ///
936 /// \param sample Pointer to the sample that will be recorded.
937 ////////////////////////////////////////////////////////////////////////////////
938 void ts5_record_sample(TS5_SAMPLE *sample)
939 {
940  ts5_check_audio_recorder2("ts5_record_sample");
941  ts5_check_audio_recorder3("ts5_record_sample", sample);
942 
943  // get some parameters
944  sample->start_time = al_get_time();
945  int channels = ts5_get_audio_channels();
946  int depth = al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
947  double samplerate = ts5_get_audio_samplerate();
948 
949  // remove buffered audio fragments
951 
952  // set buffer pointer of the sample to the beginning
953  sample->buffer_pos = sample->buffer;
954 
955  // wait for the first recorder fragment
956  ALLEGRO_EVENT event;
957  do {
958  al_wait_for_event(_ts5_data.audio.recorder_queue, &event);
959  } while(event.type != ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT);
960  ALLEGRO_AUDIO_RECORDER_EVENT *recorder_event =
961  al_get_audio_recorder_event(&event);
962 
963  // compute fragment onset and n of samples to skip
964  double fragment_onset = event.any.timestamp - recorder_event->samples / samplerate;
965  int64_t samples_to_skip = (sample->start_time - fragment_onset) * samplerate;
966 
967  if (samples_to_skip < 0) {
968  samples_to_skip = 0;
969  }
970 
971  // compute n of samples to copy
972  int64_t samples_to_copy = channels * (recorder_event->samples - samples_to_skip);
973 
974  if (samples_to_copy > sample->buffer_end - sample->buffer_pos) {
975  samples_to_copy = sample->buffer_end - sample->buffer_pos;
976  }
977 
978  if (samples_to_copy < 0) {
979  samples_to_copy = 0;
980  }
981 
982  // copy to the sample buffer
983  memcpy(sample->buffer_pos, recorder_event->buffer + samples_to_skip * channels,
984  (uint64_t)samples_to_copy * depth);
985 
986  // update buffer counter
987  sample->buffer_pos += samples_to_copy;
988 }
989 
990 
991 ////////////////////////////////////////////////////////////////////////////////
992 /// Update the sample buffer when recording.
993 ///
994 /// \param sample Pointer to the sample that will be recorded.
995 ///
996 /// \return 1 if the sample is full, 0 if not.
997 ////////////////////////////////////////////////////////////////////////////////
998 int ts5_get_sample_fragments(TS5_SAMPLE *sample)
999 {
1000  ts5_check_audio_recorder2("ts5_get_sample_fragments");
1001  ts5_check_audio_recorder3("ts5_get_sample_fragments", sample);
1002 
1003 
1004  if (sample->buffer_pos == sample->buffer) {
1005  ts5_fatal("ts5_get_sample_fragments: audio recording not started yet\n");
1006  }
1007 
1008  int channels = ts5_get_audio_channels();
1009  int depth = al_get_audio_depth_size(ALLEGRO_AUDIO_DEPTH_INT16);
1010 
1011  // update until all events are processed or until the sample is full
1012  int full = 0;
1013  ALLEGRO_EVENT event;
1014  while (!full && al_get_next_event(_ts5_data.audio.recorder_queue, &event)) {
1015 
1016  if (event.type==ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT) {
1017 
1018  ALLEGRO_AUDIO_RECORDER_EVENT *recorder_event =
1019  al_get_audio_recorder_event(&event);
1020 
1021  // compute n of samples to copy
1022  int64_t samples_to_copy = channels * recorder_event->samples;
1023  if (samples_to_copy > sample->buffer_end - sample->buffer_pos) {
1024  samples_to_copy = sample->buffer_end - sample->buffer_pos;
1025  full = 1;
1026  }
1027 
1028  // write to the buffer
1029  memcpy(sample->buffer_pos, recorder_event->buffer,
1030  (uint64_t)samples_to_copy * depth);
1031 
1032  // update buffer counter
1033  sample->buffer_pos += samples_to_copy;
1034 
1035  }
1036  }
1037  return full;
1038 }
1039 
1040 
1041 ////////////////////////////////////////////////////////////////////////////////
1042 //@}
1043 ////////////////////////////////////////////////////////////////////////////////
1044 
1045 
1046 ////////////////////////////////////////////////////////////////////////////////
1047 /// @name Software voice key
1048 /// The audio recorder can be used as a software voice key.
1049 ///
1050 /// The user has to explicitly start an audio recording to start the voice key
1051 /// and update the sample buffer with ts5_get_sample_fragments().
1052 /// The ts5_detect_voice_onsets() function will then detect voice onsets
1053 /// and offsets and notify the timer functions of each onset or offset
1054 /// that is detected.
1055 ///
1056 /// See timer.c for more information about response registration.
1057 ///
1058 /// See audio04.c for an example that shows how the software voice key works.
1059 //@{
1060 ////////////////////////////////////////////////////////////////////////////////
1061 
1062 
1063 ////////////////////////////////////////////////////////////////////////////////
1064 /// Define the software voice key as a response button.
1065 ///
1066 /// \param button Number of the button (buttons are counted from 1).
1067 ///
1068 /// \return The reponse number associated with the button.
1069 ///
1070 /// Give a positive number for the button if you want to monitor button press events,
1071 /// a negative number if you want to monitor button release events.
1072 ////////////////////////////////////////////////////////////////////////////////
1074 {
1075  ts5_check_voicekey("ts5_define_voicekey_button");
1076  ts5_log(TS5_LOGLEVEL_3, "ts5_define_voicekey_button(%d)\n", button);
1077 
1078  if (abs(button)>_ts5_status.timer.voicekey.num_buttons) {
1079  ts5_fatal("%s: %s %d, %s %d is %d\n", "ts5_define_voicekey_button",
1080  "button argument is", button,
1081  "number of voicekey buttons",
1082  _ts5_status.timer.voicekey.num_buttons);
1083  }
1084 
1085  if (button>0 && _ts5_status.timer.voicekey
1086  .button_press_defined[button-1]!=0) {
1087  ts5_fatal("%s: %s %d %s\n", "ts5_define_voicekey_button",
1088  "button press", button, "is already defined");
1089  }
1090 
1091  if (button<0 && _ts5_status.timer.voicekey
1092  .button_release_defined[-button-1]!=0) {
1093  ts5_fatal("%s: %s %d %s\n", "ts5_define_voicekey_button",
1094  "button release", button, "is already defined");
1095  }
1096 
1097  _ts5_status.timer.voicekey_is_response_device = 1;
1098  _ts5_status.timer.num_defined_buttons++;
1099  _ts5_status.timer.num_active_buttons++;
1100  _ts5_status.timer.voicekey.num_defined_buttons++;
1101  _ts5_status.timer.voicekey.num_active_buttons++;
1102 
1103  if (button>0) {
1104  _ts5_status.timer.voicekey
1105  .button_press_defined[button-1] =
1106  _ts5_status.timer.num_defined_buttons;
1107 
1108  _ts5_status.timer.voicekey
1109  .button_press_active[button-1] =
1110  _ts5_status.timer.num_defined_buttons;
1111  }
1112  else {
1113  _ts5_status.timer.voicekey
1114  .button_release_defined[-button-1] =
1115  _ts5_status.timer.num_defined_buttons;
1116 
1117  _ts5_status.timer.voicekey
1118  .button_release_active[-button-1] =
1119  _ts5_status.timer.num_defined_buttons;
1120  }
1121 
1122  return _ts5_status.timer.num_defined_buttons;
1123 }
1124 
1125 
1126 ////////////////////////////////////////////////////////////////////////////////
1127 /// Detect voice onsets in a sample.
1128 ///
1129 /// \param sample Pointer to the sample that will be processed.
1130 ////////////////////////////////////////////////////////////////////////////////
1131 void ts5_detect_voice_onsets(TS5_SAMPLE *sample)
1132 {
1133  ts5_check_voicekey("ts5_detect_voice_onsets");
1134  ts5_log(TS5_LOGLEVEL_4, "ts5_detect_voice_onsets(%p)\n", sample);
1135 
1136  if (!sample) {
1137  ts5_fatal("ts5_detect_voice_onsets: sample pointer is null\n");
1138  }
1139 
1140  if (sample->isfilestream) {
1141  ts5_fatal("ts5_detect_voice_onsets: file streams not implemented yet\n");
1142  }
1143 
1144  if (sample->ismemorystream) {
1145  ts5_fatal("ts5_detect_voice_onsets: memory streams not implemented yet\n");
1146  }
1147 
1148  if (al_get_sample_depth(sample->sample) != ALLEGRO_AUDIO_DEPTH_INT16) {
1149  ts5_fatal("ts5_detect_voice_onsets: floating point samples not implemented\n");
1150  }
1151 
1152  int channels = ts5_get_sample_channels(sample);
1153  int samplerate = al_get_sample_frequency(sample->sample);
1154  int64_t nsamples = sample->buffer_pos - sample->buffer;
1155 
1156  // rms step 1: compute sum of squares per timeslice
1157  int64_t sample_idx;
1158  int64_t timeslice = 0;
1159  for(sample_idx=0; sample_idx<nsamples; sample_idx++) {
1160  timeslice = sample_idx * 1000 / samplerate / channels;
1161  sample->rms_num_samples[timeslice]++;
1162  sample->rms[timeslice] +=
1163  (sample->buffer[sample_idx] * sample->buffer[sample_idx]);
1164  }
1165 
1166  // rms step 2: take root mean square per timeslice
1167  int max = 32767; // maximum value of 16-bit integers
1168  int64_t ntimeslices = ts5_get_sample_length(sample) * 1000;
1169  for(timeslice=0; timeslice<ntimeslices; timeslice++) {
1170  sample->rms[timeslice] =
1171  sqrt(sample->rms[timeslice]/sample->rms_num_samples[timeslice]) / max;
1172  }
1173 
1174  // rms step 3: treshold
1175  for(timeslice=0; timeslice<ntimeslices; timeslice++) {
1176 
1177  if(sample->rms[timeslice] > _ts5_status.timer.voicekey.treshold) {
1178  sample->rms[timeslice] = 1.0;
1179  }
1180  else {
1181  sample->rms[timeslice] = 0.0;
1182  }
1183  }
1184 
1185  // step 4: treshold and detect state changes
1186  int current_state, previous_state=0;
1187  int64_t last_state_toggle_time=0;
1188 
1189  for(timeslice=0; timeslice<ntimeslices; timeslice++) {
1190 
1191  if(sample->rms[timeslice] > _ts5_status.timer.voicekey.treshold) {
1192  current_state = 1;
1193  }
1194  else {
1195  current_state = 0;
1196  }
1197 
1198  if(current_state != previous_state) {
1199 
1200  int diff = timeslice - last_state_toggle_time;
1201  int rise = current_state && diff > _ts5_status.timer.voicekey.rise_delay * 1000;
1202  int drop = (!current_state) && diff > _ts5_status.timer.voicekey.drop_delay * 1000;
1203 
1204  if(rise || drop) {
1205 
1206  ALLEGRO_EVENT voicekey_event;
1207  if (rise) {
1208  voicekey_event.user.type = TS5_EVENT_VOICEKEY_BUTTON_DOWN;
1209  }
1210 
1211  if (drop) {
1212  voicekey_event.user.type = TS5_EVENT_VOICEKEY_BUTTON_UP;
1213  }
1214 
1215  voicekey_event.user.data1 = 1;
1216  voicekey_event.user.data2 = 1;
1217 
1218  // make our own timestamp: time where onset/offset is detected
1219  // allegro timestamp: time where event is emitted
1220  voicekey_event.user.data3 =
1221  (intptr_t)(timeslice*1000 - sample->start_time*1000000.0);
1222 
1223  previous_state = current_state;
1224  last_state_toggle_time = timeslice;
1225 
1226  al_emit_user_event(
1227  &_ts5_data.timer.voicekey_response_event_source,
1228  &voicekey_event, NULL);
1229  }
1230  }
1231  }
1232 
1233 }
1234 
1235 
1236 ////////////////////////////////////////////////////////////////////////////////
1237 /// Set the voice key treshold.
1238 ///
1239 /// \param treshold Treshold as a value beteen 0.0 (silence) and 1.0 (max).
1240 /// \return The previous setting.
1241 ///
1242 /// The default treshold is set to 0.001.
1243 ////////////////////////////////////////////////////////////////////////////////
1244 double ts5_set_voicekey_treshold(double treshold)
1245 {
1246  ts5_check_voicekey("ts5_set_voicekey_treshold");
1247  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_treshold(%f)\n", treshold);
1248 
1249  if (treshold < 0.0) {
1250  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_treshold",
1251  "treshold should be positive", treshold);
1252  }
1253 
1254  if (treshold > 1.0) {
1255  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_treshold",
1256  "treshold should be smaller than 1.0", treshold);
1257  }
1258 
1259  double retval =
1260  _ts5_status.timer.voicekey.treshold;
1261 
1262  _ts5_status.timer.voicekey.treshold = treshold;
1263 
1264  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1265  "ts5_set_voicekey_treshold",
1266  "set voice key treshold",
1267  _ts5_status.timer.voicekey.treshold,
1268  retval);
1269 
1270  return retval;
1271 }
1272 
1273 
1274 ////////////////////////////////////////////////////////////////////////////////
1275 /// Get the voice key treshold.
1276 ///
1277 /// \return The voice key treshold.
1278 ////////////////////////////////////////////////////////////////////////////////
1280 {
1281  ts5_check_voicekey("ts5_get_voicekey_treshold");
1282  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_treshold\n");
1283 
1284  return _ts5_status.timer.voicekey.treshold;
1285 }
1286 
1287 
1288 ////////////////////////////////////////////////////////////////////////////////
1289 /// Set the voice key rise delay.
1290 ///
1291 /// \param rise_delay Rise delay in seconds.
1292 /// \return The previous setting.
1293 ///
1294 /// The default rise delay is set to 0.2 seconds.
1295 ////////////////////////////////////////////////////////////////////////////////
1296 double ts5_set_voicekey_rise_delay(double rise_delay)
1297 {
1298  ts5_check_voicekey("ts5_set_voicekey_rise_delay");
1299  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_rise_delay(%f)\n", rise_delay);
1300 
1301  if (rise_delay < 0.0) {
1302  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_rise_delay",
1303  "rise_delay should be positive", rise_delay);
1304  }
1305 
1306  double retval = _ts5_status.timer.voicekey.rise_delay;
1307 
1308  _ts5_status.timer.voicekey.rise_delay = rise_delay;
1309 
1310  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1311  "ts5_set_voicekey_rise_delay",
1312  "set voice key rise_delay",
1313  _ts5_status.timer.voicekey.rise_delay,
1314  retval);
1315 
1316  return retval;
1317 }
1318 
1319 
1320 ////////////////////////////////////////////////////////////////////////////////
1321 /// Get the voice key rise delay.
1322 ///
1323 /// \return The voice key rise delay.
1324 ////////////////////////////////////////////////////////////////////////////////
1326 {
1327  ts5_check_voicekey("ts5_get_voicekey_rise_delay");
1328  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_rise_delay\n");
1329 
1330  return _ts5_status.timer.voicekey.rise_delay;
1331 }
1332 
1333 
1334 
1335 ////////////////////////////////////////////////////////////////////////////////
1336 /// Set the voice key drop delay.
1337 ///
1338 /// \param drop_delay Rise delay in seconds.
1339 /// \return The previous setting.
1340 ///
1341 /// The default drop delay is set to 0.2 seconds.
1342 ////////////////////////////////////////////////////////////////////////////////
1343 double ts5_set_voicekey_drop_delay(double drop_delay)
1344 {
1345  ts5_check_voicekey("ts5_set_voicekey_drop_delay");
1346  ts5_log(TS5_LOGLEVEL_4, "ts5_set_voicekey_drop_delay(%f)\n", drop_delay);
1347 
1348  if (drop_delay < 0.0) {
1349  ts5_fatal("%s: %s (is %f)\n", "ts5_set_voicekey_drop_delay",
1350  "drop_delay should be positive", drop_delay);
1351  }
1352 
1353  double retval = _ts5_status.timer.voicekey.drop_delay;
1354 
1355  _ts5_status.timer.voicekey.drop_delay = drop_delay;
1356 
1357  ts5_log(TS5_LOGLEVEL_4, "%s: %s to %f (was %f)\n",
1358  "ts5_set_voicekey_drop_delay",
1359  "set voice key drop_delay",
1360  _ts5_status.timer.voicekey.drop_delay,
1361  retval);
1362 
1363  return retval;
1364 }
1365 
1366 
1367 ////////////////////////////////////////////////////////////////////////////////
1368 /// Get the voice key drop delay.
1369 ///
1370 /// \return The voice key drop delay.
1371 ////////////////////////////////////////////////////////////////////////////////
1373 {
1374  ts5_check_voicekey("ts5_get_voicekey_drop_delay");
1375  ts5_log(TS5_LOGLEVEL_4, "ts5_get_voicekey_drop_delay\n");
1376 
1377  return _ts5_status.timer.voicekey.drop_delay;
1378 }
1379 
1380 
1381 ////////////////////////////////////////////////////////////////////////////////
1382 //@}
1383 ////////////////////////////////////////////////////////////////////////////////
1384 
1385 
1386 
1387 ////////////////////////////////////////////////////////////////////////////////
1388 /// @name Sample parameters
1389 /// For each sample the parameters can be queried/set using the functions below:
1390 ///
1391 /// - Sample position, speed, gain, pan and playmode
1392 /// can be adjusted at any time, even when the sample is playing.
1393 /// - Samplerate, channels, depth and length are defined when the
1394 /// sample is read or allocated.
1395 ///
1396 //@{
1397 ////////////////////////////////////////////////////////////////////////////////
1398 
1399 
1400 ////////////////////////////////////////////////////////////////////////////////
1401 /// Get the sample rate of a sample.
1402 ///
1403 /// \param sample Pointer to the sample that will queried.
1404 ///
1405 /// \return The sample rate of the sample.
1406 ////////////////////////////////////////////////////////////////////////////////
1407 unsigned int ts5_get_sample_samplerate(TS5_SAMPLE *sample)
1408 {
1409  ts5_check_audio("ts5_get_sample_samplerate");
1410  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_samplerate(%p)\n", sample);
1411 
1412  if (!sample) {
1413  ts5_fatal("ts5_get_sample_samplerate: sample pointer is null\n");
1414  }
1415 
1416  unsigned int retval = 0;
1417 
1418  if (sample->issample) {
1419  retval = al_get_sample_frequency(sample->sample);
1420  }
1421  else if (sample->isfilestream) {
1422  retval = al_get_audio_stream_frequency(sample->stream);
1423  }
1424  else if (sample->ismemorystream) {
1425  ts5_fatal("%s: %s\n", "ts5_get_sample_samplerate",
1426  "memory streams not implemented yet");
1427  }
1428 
1429  return retval;
1430 }
1431 
1432 
1433 ////////////////////////////////////////////////////////////////////////////////
1434 /// Get the number of channels of a sample.
1435 ///
1436 /// \param sample Pointer to the sample that will queried.
1437 ///
1438 /// \return The number of channels of the sample.
1439 ////////////////////////////////////////////////////////////////////////////////
1440 unsigned int ts5_get_sample_channels(TS5_SAMPLE *sample)
1441 {
1442  ts5_check_audio("ts5_get_sample_channels");
1443  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_channels(%p)\n", sample);
1444 
1445  if (!sample) {
1446  ts5_fatal("ts5_get_sample_channels: sample pointer is null\n");
1447  }
1448 
1449  ALLEGRO_CHANNEL_CONF channels = 0;
1450 
1451  if (sample->issample) {
1452  channels = al_get_sample_channels(sample->sample);
1453  }
1454  else if (sample->isfilestream) {
1455  channels = al_get_audio_stream_channels(sample->stream);
1456  }
1457  else if (sample->ismemorystream) {
1458  ts5_fatal("%s: %s\n", "ts5_get_sample_channels",
1459  "memory streams not implemented yet");
1460  }
1461 
1462  unsigned int retval = 0;
1463 
1464  if (channels == ALLEGRO_CHANNEL_CONF_1) {
1465  retval = TS5_MONO;
1466  }
1467  else if (channels == ALLEGRO_CHANNEL_CONF_2) {
1468  retval = TS5_STEREO;
1469  }
1470  else {
1471  ts5_fatal("%s: %s\n", "ts5_get_sample_channels",
1472  "got an unknown number of channels");
1473  }
1474 
1475  return retval;
1476 }
1477 
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// Get the sample depth of a sample.
1481 ///
1482 /// \param sample Pointer to the sample that will queried.
1483 ///
1484 /// \return The sample depth of a sample.
1485 ////////////////////////////////////////////////////////////////////////////////
1486 int ts5_get_sample_depth(TS5_SAMPLE *sample)
1487 {
1488  ts5_check_audio("ts5_get_sample_depth");
1489  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_depth(%p)\n", sample);
1490 
1491  if (!sample) {
1492  ts5_fatal("ts5_get_sample_depth: sample pointer is null\n");
1493  }
1494 
1495  ALLEGRO_AUDIO_DEPTH depth = 0;
1496 
1497  if (sample->issample) {
1498  depth = al_get_sample_depth(sample->sample);
1499  }
1500  else if (sample->isfilestream) {
1501  depth = al_get_audio_stream_depth(sample->stream);
1502  }
1503  else if (sample->ismemorystream) {
1504  ts5_fatal("ts5_get_sample_depth: memory streams not implemented yet\n");
1505  }
1506 
1507  int retval = 0;
1508 
1509  if (depth == ALLEGRO_AUDIO_DEPTH_INT16) {
1510  retval = TS5_INTEGER;
1511  }
1512  else if (depth == ALLEGRO_AUDIO_DEPTH_FLOAT32) {
1513  retval = TS5_FLOAT;
1514  }
1515  else {
1516  ts5_fatal("ts5_get_audio_depth: got an unknown sample depth\n");
1517  }
1518 
1519  return retval;
1520 }
1521 
1522 
1523 ////////////////////////////////////////////////////////////////////////////////
1524 /// Get the length of a sample.
1525 ///
1526 /// \param sample Pointer to the sample that will queried.
1527 ///
1528 /// \return The length of the sample.
1529 ////////////////////////////////////////////////////////////////////////////////
1530 double ts5_get_sample_length(TS5_SAMPLE *sample)
1531 {
1532  ts5_check_audio("ts5_get_sample_length");
1533  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_length(%p)\n", sample);
1534 
1535  if (!sample) {
1536  ts5_fatal("ts5_get_sample_length: sample pointer is null\n");
1537  }
1538 
1539  double retval = 0.0;
1540 
1541  if (sample->issample) {
1542  double freq = al_get_sample_frequency(sample->sample);
1543  retval = (double)al_get_sample_length(sample->sample) / freq;
1544  }
1545  else if (sample->isfilestream) {
1546  retval = al_get_audio_stream_length_secs(sample->stream);
1547  }
1548  else if (sample->ismemorystream) {
1549  ts5_fatal("%s: %s\n", "ts5_get_sample_length",
1550  "memory streams not implemented yet");
1551  }
1552 
1553  return retval;
1554 }
1555 
1556 
1557 ////////////////////////////////////////////////////////////////////////////////
1558 /// Set the playback position of a sample.
1559 ///
1560 /// \param sample Pointer to the sample that will be adjusted.
1561 /// \param position The new playback position.
1562 ///
1563 /// \return The old playback position.
1564 ////////////////////////////////////////////////////////////////////////////////
1565 double ts5_set_sample_position(TS5_SAMPLE *sample, double position)
1566 {
1567  ts5_check_audio("ts5_set_sample_position");
1568 
1569  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_position(%p,%u)\n",
1570  sample, position);
1571 
1572  if (!sample) {
1573  ts5_fatal("ts5_set_sample_position: sample pointer is null\n");
1574  }
1575 
1576  double retval = 0.0;
1577 
1578  if (sample->issample) {
1579 
1580  double freq = al_get_sample_frequency(sample->sample);
1581  double max = al_get_sample_length(sample->sample) / freq;
1582 
1583  if (position > max) {
1584  ts5_fatal("ts5_set_sample_position: position should be",
1585  " <= the length of the sample (%f)\n", max);
1586  }
1587 
1588  retval = al_get_sample_instance_position(sample->instance) / freq;
1589 
1590  if (!(al_set_sample_instance_position(sample->instance, position*freq))) {
1591  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1592  "could not change sample position");
1593  }
1594  }
1595  else if (sample->isfilestream) {
1596 
1597  unsigned int max = al_get_audio_stream_length_secs(sample->stream);
1598 
1599  if (position > max) {
1600  ts5_fatal("ts5_set_sample_position: position should be",
1601  " <= the length of the sample (%f)\n", max);
1602  }
1603 
1604  retval = al_get_audio_stream_position_secs(sample->stream);
1605 
1606  if (!(al_seek_audio_stream_secs(sample->stream, position))) {
1607  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1608  "could not change sample position");
1609  }
1610  }
1611  else if (sample->ismemorystream) {
1612  ts5_fatal("%s: %s\n", "ts5_set_sample_position",
1613  "memory streams not implemented yet");
1614  }
1615 
1616  return retval;
1617 }
1618 
1619 
1620 ////////////////////////////////////////////////////////////////////////////////
1621 /// Get the playback position of a sample.
1622 ///
1623 /// \param sample Pointer to the sample that will be queried.
1624 ///
1625 /// \return The current playback position.
1626 ////////////////////////////////////////////////////////////////////////////////
1627 double ts5_get_sample_position(TS5_SAMPLE *sample)
1628 {
1629  ts5_check_audio("ts5_get_sample_position");
1630  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_position(%p)\n", sample);
1631 
1632  if (!sample) {
1633  ts5_fatal("ts5_get_sample_length: sample pointer is null\n");
1634  }
1635 
1636  double retval = 0.0;
1637 
1638  if (sample->issample) {
1639  double freq = al_get_sample_frequency(sample->sample);
1640  retval = al_get_sample_instance_position(sample->instance) / freq;
1641  }
1642  else if (sample->isfilestream) {
1643  retval = al_get_audio_stream_position_secs(sample->stream);
1644  }
1645  else if (sample->ismemorystream) {
1646  ts5_fatal("%s: %s\n", "ts5_get_sample_position",
1647  "memory streams not implemented yet");
1648  }
1649 
1650  return retval;
1651 }
1652 
1653 
1654 ////////////////////////////////////////////////////////////////////////////////
1655 /// Set the playback speed of a sample.
1656 ///
1657 /// \param sample Pointer to the sample that will be adjusted.
1658 /// \param speed The new playback speed (1.0 is normal speed).
1659 ///
1660 /// \return The old playback speed.
1661 ////////////////////////////////////////////////////////////////////////////////
1662 double ts5_set_sample_speed(TS5_SAMPLE *sample, double speed)
1663 {
1664  ts5_check_audio("ts5_set_sample_speed");
1665  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_speed(%p,%f)\n", sample, speed);
1666 
1667  if (!sample) {
1668  ts5_fatal("ts5_set_sample_speed: sample pointer is null\n");
1669  }
1670 
1671  if (speed < 0) {
1672  ts5_fatal("ts5_set_sample_speed: speed should be >0 (is %f)\n", speed);
1673  }
1674 
1675  double retval = 0.0;
1676 
1677  if (sample->issample) {
1678 
1679  retval = al_get_sample_instance_speed(sample->instance);
1680 
1681  if (!(al_set_sample_instance_speed(sample->instance, speed))) {
1682  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_speed",
1683  "could not change sample speed", speed);
1684  }
1685  }
1686  else if (sample->isfilestream) {
1687 
1688  retval = al_get_audio_stream_speed(sample->stream);
1689 
1690  if (!(al_set_audio_stream_speed(sample->stream, speed))) {
1691  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_speed",
1692  "could not change sample speed", speed);
1693  }
1694  }
1695  else if (sample->ismemorystream) {
1696  ts5_fatal("%s: %s\n", "ts5_set_sample_speed",
1697  "memory streams not implemented yet");
1698  }
1699 
1700  return retval;
1701 }
1702 
1703 
1704 ////////////////////////////////////////////////////////////////////////////////
1705 /// Get the playback speed of a sample.
1706 ///
1707 /// \param sample Pointer to the sample that will be queried.
1708 ///
1709 /// \return The current playback speed.
1710 ////////////////////////////////////////////////////////////////////////////////
1711 double ts5_get_sample_speed(TS5_SAMPLE *sample)
1712 {
1713  ts5_check_audio("ts5_get_sample_speed");
1714  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_speed(%p)\n", sample);
1715 
1716  if (!sample) {
1717  ts5_fatal("ts5_get_sample_speed: sample pointer is null\n");
1718  }
1719 
1720  double retval = 0.0;
1721 
1722  if (sample->issample) {
1723  retval = al_get_sample_instance_speed(sample->instance);
1724  }
1725  else if (sample->isfilestream) {
1726  retval = al_get_audio_stream_speed(sample->stream);
1727  }
1728  else if (sample->ismemorystream) {
1729  ts5_fatal("ts5_get_sample_speed: memory streams not implemented yet\n");
1730  }
1731 
1732  return retval;
1733 }
1734 
1735 
1736 ////////////////////////////////////////////////////////////////////////////////
1737 /// Set the playback gain of a sample.
1738 ///
1739 /// \param sample Pointer to the sample that will be adjusted.
1740 /// \param gain The new playback gain (1.0 is normal gain).
1741 ///
1742 /// \return The old gain setting.
1743 ////////////////////////////////////////////////////////////////////////////////
1744 double ts5_set_sample_gain(TS5_SAMPLE *sample, double gain)
1745 {
1746  ts5_check_audio("ts5_set_sample_gain");
1747  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_gain(%p,%f)\n", sample, gain);
1748 
1749  if (!sample) {
1750  ts5_fatal("ts5_set_sample_gain: sample pointer is null\n");
1751  }
1752 
1753  if (gain < 0) {
1754  ts5_fatal("ts5_set_sample_gain: gain should be >0 (is %f)\n", gain);
1755  }
1756 
1757  double retval = 0.0;
1758 
1759  if (sample->issample) {
1760 
1761  retval = al_get_sample_instance_gain(sample->instance);
1762 
1763  if (!(al_set_sample_instance_gain(sample->instance, gain))) {
1764  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_gain",
1765  "could not change sample gain", gain);
1766  }
1767  }
1768  else if (sample->isfilestream) {
1769 
1770  retval = al_get_audio_stream_gain(sample->stream);
1771 
1772  if (!(al_set_audio_stream_gain(sample->stream, gain))) {
1773  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_gain",
1774  "could not change sample gain", gain);
1775  }
1776  }
1777  else if (sample->ismemorystream) {
1778  ts5_fatal("ts5_set_sample_gain: memory streams not implemented yet\n");
1779  }
1780 
1781  return retval;
1782 }
1783 
1784 
1785 ////////////////////////////////////////////////////////////////////////////////
1786 /// Get the playback gain of a sample.
1787 ///
1788 /// \param sample Pointer to the sample that will be queried.
1789 ///
1790 /// \return The current playback gain.
1791 ////////////////////////////////////////////////////////////////////////////////
1792 double ts5_get_sample_gain(TS5_SAMPLE *sample)
1793 {
1794  ts5_check_audio("ts5_get_sample_gain");
1795  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_gain(%p)\n", sample);
1796 
1797  if (!sample) {
1798  ts5_fatal("ts5_get_sample_gain: sample pointer is null\n");
1799  }
1800 
1801  double retval = 0.0;
1802 
1803  if (sample->issample) {
1804  retval = al_get_sample_instance_gain(sample->instance);
1805  }
1806  else if (sample->isfilestream) {
1807  retval = al_get_audio_stream_gain(sample->stream);
1808  }
1809  else if (sample->ismemorystream) {
1810  ts5_fatal("ts5_get_sample_gain: memory streams not implemented yet\n");
1811  }
1812 
1813  return retval;
1814 }
1815 
1816 
1817 ////////////////////////////////////////////////////////////////////////////////
1818 /// Set the playback pan of a sample.
1819 ///
1820 /// \param sample Pointer to the sample that will be adjusted.
1821 /// \param pan The new playback pan
1822 /// (-1.0 is left, 0.0 is normal, 1.0 is right).
1823 ///
1824 /// \return The old playback pan.
1825 ////////////////////////////////////////////////////////////////////////////////
1826 double ts5_set_sample_pan(TS5_SAMPLE *sample, double pan)
1827 {
1828  ts5_check_audio("ts5_set_sample_pan");
1829  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_pan(%p,%f)\n", sample, pan);
1830 
1831  if (!sample) {
1832  ts5_fatal("ts5_set_sample_pan: sample pointer is null\n");
1833  }
1834 
1835  if (pan < -1.0 || pan > 1) {
1836  ts5_fatal("%s: %s (is %f)\n", "ts5_set_sample_pan",
1837  "pan should be between -1.0 and 1.0", pan);
1838  }
1839 
1840  double retval = 0.0;
1841 
1842  if (sample->issample) {
1843 
1844  retval = al_get_sample_instance_pan(sample->instance);
1845 
1846  if (!(al_set_sample_instance_pan(sample->instance, pan))) {
1847  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_pan",
1848  "could not change sample pan", pan);
1849  }
1850  }
1851  else if (sample->isfilestream) {
1852 
1853  retval = al_get_audio_stream_pan(sample->stream);
1854 
1855  if (!(al_set_audio_stream_pan(sample->stream, pan))) {
1856  ts5_fatal("%s: %s (%f)\n", "ts5_set_sample_pan",
1857  "could not change sample pan", pan);
1858  }
1859  }
1860  else if (sample->ismemorystream) {
1861  ts5_fatal("ts5_set_sample_pan: memory streams not implemented yet\n");
1862  }
1863 
1864  return retval;
1865 }
1866 
1867 
1868 ////////////////////////////////////////////////////////////////////////////////
1869 /// Get the playback pan of a sample.
1870 ///
1871 /// \param sample Pointer to the sample that will be queried.
1872 ///
1873 /// \return The current playback pan.
1874 ////////////////////////////////////////////////////////////////////////////////
1875 double ts5_get_sample_pan(TS5_SAMPLE *sample)
1876 {
1877  ts5_check_audio("ts5_get_sample_pan");
1878  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_pan(%p)\n", sample);
1879 
1880  if (!sample) {
1881  ts5_fatal("ts5_get_sample_pan: sample pointer is null\n");
1882  }
1883 
1884  double retval = 0.0;
1885 
1886  if (sample->issample) {
1887  retval = al_get_sample_instance_pan(sample->instance);
1888  }
1889  else if (sample->isfilestream) {
1890  retval = al_get_audio_stream_pan(sample->stream);
1891  }
1892  else if (sample->ismemorystream) {
1893  ts5_fatal("memory streams not implemented yet\n");
1894  }
1895 
1896  return retval;
1897 }
1898 
1899 
1900 ////////////////////////////////////////////////////////////////////////////////
1901 /// Set the playmode of a sample.
1902 ///
1903 /// \param sample Pointer to the sample that will be adjusted.
1904 /// \param playmode The new playmode. Can be TS5_PLAY_ONCE or TS5_PLAY_LOOP.
1905 ///
1906 /// \return The old playmode.
1907 ////////////////////////////////////////////////////////////////////////////////
1908 int ts5_set_sample_playmode(TS5_SAMPLE *sample, int playmode)
1909 {
1910  ts5_check_audio("ts5_set_sample_playmode");
1911  ts5_log(TS5_LOGLEVEL_4, "ts5_set_sample_playmode(%p,%d)\n",
1912  sample, playmode);
1913 
1914  if (!sample) {
1915  ts5_fatal("ts5_set_sample_playmode: sample pointer is null\n");
1916  }
1917 
1918  if (playmode != TS5_PLAY_ONCE && playmode != TS5_PLAY_LOOP) {
1919  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1920  "playmode should be TS5_PLAY_ONCE or TS5_PLAY_LOOP");
1921  }
1922 
1923  int retval = 0;
1924 
1925  if (sample->issample) {
1926 
1927  retval = al_get_sample_instance_playmode(sample->instance);
1928 
1929  if (!(al_set_sample_instance_playmode(sample->instance, playmode))) {
1930  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1931  "could not change sample playmode");
1932  }
1933  }
1934  else if (sample->isfilestream) {
1935 
1936  retval = al_get_audio_stream_playmode(sample->stream) - 3;
1937 
1938  if (!(al_set_audio_stream_playmode(sample->stream, playmode))) {
1939  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1940  "could not change sample playmode");
1941  }
1942  }
1943  else if (sample->ismemorystream) {
1944  ts5_fatal("%s: %s\n", "ts5_set_sample_playmode",
1945  "memory streams not implemented yet");
1946  }
1947 
1948  return retval;
1949 }
1950 
1951 
1952 ////////////////////////////////////////////////////////////////////////////////
1953 /// Get the playmode of a sample.
1954 ///
1955 /// \param sample Pointer to the sample that will be queried.
1956 ///
1957 /// \return The current playmode.
1958 ////////////////////////////////////////////////////////////////////////////////
1959 int ts5_get_sample_playmode(TS5_SAMPLE *sample)
1960 {
1961  ts5_check_audio("ts5_get_sample_playmode");
1962  ts5_log(TS5_LOGLEVEL_4, "ts5_get_sample_playmode(%p)\n", sample);
1963 
1964  if (!sample) {
1965  ts5_fatal("ts5_get_sample_playmode: sample pointer is null\n");
1966  }
1967 
1968  int retval = 0;
1969 
1970  if (sample->issample) {
1971  retval = al_get_sample_instance_playmode(sample->instance);
1972  }
1973  else if (sample->isfilestream) {
1974  retval = al_get_audio_stream_playmode(sample->stream) - 3;
1975  }
1976  else if (sample->ismemorystream) {
1977  ts5_fatal("%s: %s\n", "ts5_get_sample_playmode",
1978  "memory streams not implemented yet");
1979  }
1980 
1981  return retval;
1982 }
1983 
1984 
1985 ////////////////////////////////////////////////////////////////////////////////
1986 //@}
1987 ////////////////////////////////////////////////////////////////////////////////
1988 
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:1959
void ts5_record_sample(TS5_SAMPLE *sample)
Start recording a sample.
Definition: audio.c:938
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:1296
void ts5_flush_audio_recorder()
Flush the audio recorder buffer.
Definition: audio.c:926
double ts5_get_sample_speed(TS5_SAMPLE *sample)
Get the playback speed of a sample.
Definition: audio.c:1711
void ts5_write_sample(const char *file, TS5_SAMPLE *sample)
Write a sample.
Definition: audio.c:595
unsigned int ts5_get_sample_channels(TS5_SAMPLE *sample)
Get the number of channels of a sample.
Definition: audio.c:1440
void ts5_detect_voice_onsets(TS5_SAMPLE *sample)
Detect voice onsets in a sample.
Definition: audio.c:1131
double ts5_get_voicekey_treshold()
Get the voice key treshold.
Definition: audio.c:1279
double ts5_set_sample_speed(TS5_SAMPLE *sample, double speed)
Set the playback speed of a sample.
Definition: audio.c:1662
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:998
double ts5_get_voicekey_drop_delay()
Get the voice key drop delay.
Definition: audio.c:1372
unsigned int ts5_get_sample_samplerate(TS5_SAMPLE *sample)
Get the sample rate of a sample.
Definition: audio.c:1407
void * ts5_get_sample_data_pointer(TS5_SAMPLE *sample)
Get acces to a sample&#39;s data.
Definition: audio.c:831
void ts5_stop_audio_recorder()
Stop the audio recorder.
Definition: audio.c:912
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:896
double ts5_get_sample_length(TS5_SAMPLE *sample)
Get the length of a sample.
Definition: audio.c:1530
double ts5_get_sample_position(TS5_SAMPLE *sample)
Get the playback position of a sample.
Definition: audio.c:1627
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:1325
int ts5_get_sample_status(TS5_SAMPLE *sample)
Query whether a sample is playing.
Definition: audio.c:771
double ts5_get_sample_pan(TS5_SAMPLE *sample)
Get the playback pan of a sample.
Definition: audio.c:1875
double ts5_set_voicekey_treshold(double treshold)
Set the voice key treshold.
Definition: audio.c:1244
void ts5_install_tscope5(char *calling_function)
Install Tscope5.
void ts5_stop_sample(TS5_SAMPLE *sample)
Stop playing a sample.
Definition: audio.c:731
double ts5_get_sample_gain(TS5_SAMPLE *sample)
Get the playback gain of a sample.
Definition: audio.c:1792
void ts5_play_sample(TS5_SAMPLE *sample)
Start playing a sample.
Definition: audio.c:667
int ts5_set_sample_playmode(TS5_SAMPLE *sample, int playmode)
Set the playmode of a sample.
Definition: audio.c:1908
int ts5_define_voicekey_button(int button)
Define the software voice key as a response button.
Definition: audio.c:1073
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:1486
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:619
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:699
void ts5_fatal(const char *format,...)
Exit safely with an error message.
Definition: system.c:529
double ts5_set_sample_gain(TS5_SAMPLE *sample, double gain)
Set the playback gain of a sample.
Definition: audio.c:1744
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:1565
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:1826
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:1343
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:532
TS5_SAMPLE * ts5_read_sample(const char *file)
Open a sample from a file.
Definition: audio.c:440