291f05399059d1536d2e204131d01ae033655673
[blender.git] / intern / audaspace / intern / AUD_C-API.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * AudaSpace is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #ifdef WITH_PYTHON
27 #include "AUD_PyAPI.h"
28
29 Device* g_device;
30 bool g_pyinitialized = false;
31 #endif
32
33 // needed for INT64_C
34 #ifndef __STDC_CONSTANT_MACROS
35 #define __STDC_CONSTANT_MACROS
36 #endif
37
38 #include <cstdlib>
39 #include <cstring>
40 #include <cmath>
41
42 #include "AUD_NULLDevice.h"
43 #include "AUD_I3DDevice.h"
44 #include "AUD_FileFactory.h"
45 #include "AUD_StreamBufferFactory.h"
46 #include "AUD_DelayFactory.h"
47 #include "AUD_LimiterFactory.h"
48 #include "AUD_PingPongFactory.h"
49 #include "AUD_LoopFactory.h"
50 #include "AUD_RectifyFactory.h"
51 #include "AUD_EnvelopeFactory.h"
52 #include "AUD_LinearResampleFactory.h"
53 #include "AUD_LowpassFactory.h"
54 #include "AUD_HighpassFactory.h"
55 #include "AUD_AccumulatorFactory.h"
56 #include "AUD_SumFactory.h"
57 #include "AUD_SquareFactory.h"
58 #include "AUD_ChannelMapperFactory.h"
59 #include "AUD_Buffer.h"
60 #include "AUD_ReadDevice.h"
61 #include "AUD_IReader.h"
62 #include "AUD_SequencerFactory.h"
63 #include "AUD_SilenceFactory.h"
64
65 #ifdef WITH_SDL
66 #include "AUD_SDLDevice.h"
67 #endif
68
69 #ifdef WITH_OPENAL
70 #include "AUD_OpenALDevice.h"
71 #endif
72
73 #ifdef WITH_JACK
74 #include "AUD_JackDevice.h"
75 #endif
76
77
78 #ifdef WITH_FFMPEG
79 extern "C" {
80 #include <libavformat/avformat.h>
81 }
82 #endif
83
84 #include <cassert>
85
86 typedef AUD_IFactory AUD_Sound;
87 typedef AUD_ReadDevice AUD_Device;
88 typedef AUD_Handle AUD_Channel;
89
90 #define AUD_CAPI_IMPLEMENTATION
91 #include "AUD_C-API.h"
92
93 #ifndef NULL
94 #define NULL 0
95 #endif
96
97 static AUD_IDevice* AUD_device = NULL;
98 static int AUD_available_devices[4];
99 static AUD_I3DDevice* AUD_3ddevice = NULL;
100
101 void AUD_initOnce()
102 {
103 #ifdef WITH_FFMPEG
104         av_register_all();
105 #endif
106 }
107
108 int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
109 {
110         AUD_IDevice* dev = NULL;
111
112         if(AUD_device)
113                 AUD_exit();
114
115         try
116         {
117                 switch(device)
118                 {
119                 case AUD_NULL_DEVICE:
120                         dev = new AUD_NULLDevice();
121                         break;
122 #ifdef WITH_SDL
123                 case AUD_SDL_DEVICE:
124                         dev = new AUD_SDLDevice(specs, buffersize);
125                         break;
126 #endif
127 #ifdef WITH_OPENAL
128                 case AUD_OPENAL_DEVICE:
129                         dev = new AUD_OpenALDevice(specs, buffersize);
130                         break;
131 #endif
132 #ifdef WITH_JACK
133                 case AUD_JACK_DEVICE:
134                         dev = new AUD_JackDevice("Blender", specs, buffersize);
135                         break;
136 #endif
137                 default:
138                         return false;
139                 }
140
141                 AUD_device = dev;
142                 AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
143
144 #ifdef WITH_PYTHON
145                 if(g_pyinitialized)
146                 {
147                         g_device = (Device*)Device_empty();
148                         if(g_device != NULL)
149                         {
150                                 g_device->device = dev;
151                         }
152                 }
153 #endif
154
155                 return true;
156         }
157         catch(AUD_Exception&)
158         {
159                 return false;
160         }
161 }
162
163 int* AUD_enumDevices()
164 {
165         int i = 0;
166 #ifdef WITH_SDL
167         AUD_available_devices[i++] = AUD_SDL_DEVICE;
168 #endif
169 #ifdef WITH_OPENAL
170         AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
171 #endif
172 #ifdef WITH_JACK
173         AUD_available_devices[i++] = AUD_JACK_DEVICE;
174 #endif
175         AUD_available_devices[i++] = AUD_NULL_DEVICE;
176         return AUD_available_devices;
177 }
178
179 void AUD_exit()
180 {
181 #ifdef WITH_PYTHON
182         if(g_device)
183         {
184                 Py_XDECREF(g_device);
185                 g_device = NULL;
186         }
187         else
188 #endif
189         if(AUD_device)
190                 delete AUD_device;
191         AUD_device = NULL;
192         AUD_3ddevice = NULL;
193 }
194
195 #ifdef WITH_PYTHON
196 static PyObject* AUD_getCDevice(PyObject* self)
197 {
198         if(g_device)
199         {
200                 Py_INCREF(g_device);
201                 return (PyObject*)g_device;
202         }
203         Py_RETURN_NONE;
204 }
205
206 static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS,
207                                                                                   "device()\n\n"
208                                                                                   "Returns the application's :class:`Device`.\n\n"
209                                                                                   ":return: The application's :class:`Device`.\n"
210                                                                                   ":rtype: :class:`Device`"}};
211
212 PyObject* AUD_initPython()
213 {
214         PyObject* module = PyInit_aud();
215         PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL));
216         PyDict_SetItemString(PySys_GetObject("modules"), "aud", module);
217         if(AUD_device)
218         {
219                 g_device = (Device*)Device_empty();
220                 if(g_device != NULL)
221                 {
222                         g_device->device = AUD_device;
223                 }
224         }
225         g_pyinitialized = true;
226
227         return module;
228 }
229 #endif
230
231 void AUD_lock()
232 {
233         assert(AUD_device);
234         AUD_device->lock();
235 }
236
237 void AUD_unlock()
238 {
239         assert(AUD_device);
240         AUD_device->unlock();
241 }
242
243 AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
244 {
245         assert(sound);
246
247         AUD_SoundInfo info;
248         info.specs.channels = AUD_CHANNELS_INVALID;
249         info.specs.rate = AUD_RATE_INVALID;
250         info.length = 0.0f;
251
252         try
253         {
254                 AUD_IReader* reader = sound->createReader();
255
256                 if(reader)
257                 {
258                         info.specs = reader->getSpecs();
259                         info.length = reader->getLength() / (float) info.specs.rate;
260                 }
261         }
262         catch(AUD_Exception&)
263         {
264         }
265
266         return info;
267 }
268
269 AUD_Sound* AUD_load(const char* filename)
270 {
271         assert(filename);
272         return new AUD_FileFactory(filename);
273 }
274
275 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
276 {
277         assert(buffer);
278         return new AUD_FileFactory(buffer, size);
279 }
280
281 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
282 {
283         assert(sound);
284
285         try
286         {
287                 return new AUD_StreamBufferFactory(sound);
288         }
289         catch(AUD_Exception&)
290         {
291                 return NULL;
292         }
293 }
294
295 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
296 {
297         assert(sound);
298
299         try
300         {
301                 return new AUD_DelayFactory(sound, delay);
302         }
303         catch(AUD_Exception&)
304         {
305                 return NULL;
306         }
307 }
308
309 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
310 {
311         assert(sound);
312
313         try
314         {
315                 return new AUD_LimiterFactory(sound, start, end);
316         }
317         catch(AUD_Exception&)
318         {
319                 return NULL;
320         }
321 }
322
323 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
324 {
325         assert(sound);
326
327         try
328         {
329                 return new AUD_PingPongFactory(sound);
330         }
331         catch(AUD_Exception&)
332         {
333                 return NULL;
334         }
335 }
336
337 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
338 {
339         assert(sound);
340
341         try
342         {
343                 return new AUD_LoopFactory(sound);
344         }
345         catch(AUD_Exception&)
346         {
347                 return NULL;
348         }
349 }
350
351 int AUD_setLoop(AUD_Channel* handle, int loops)
352 {
353         if(handle)
354         {
355                 try
356                 {
357                         return AUD_device->setLoopCount(handle, loops);
358                 }
359                 catch(AUD_Exception&)
360                 {
361                 }
362         }
363         return false;
364 }
365
366 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
367 {
368         assert(sound);
369
370         try
371         {
372                 return new AUD_RectifyFactory(sound);
373         }
374         catch(AUD_Exception&)
375         {
376                 return NULL;
377         }
378 }
379
380 void AUD_unload(AUD_Sound* sound)
381 {
382         assert(sound);
383         delete sound;
384 }
385
386 AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
387 {
388         assert(AUD_device);
389         assert(sound);
390         try
391         {
392                 return AUD_device->play(sound, keep);
393         }
394         catch(AUD_Exception&)
395         {
396                 return NULL;
397         }
398 }
399
400 int AUD_pause(AUD_Channel* handle)
401 {
402         assert(AUD_device);
403         return AUD_device->pause(handle);
404 }
405
406 int AUD_resume(AUD_Channel* handle)
407 {
408         assert(AUD_device);
409         return AUD_device->resume(handle);
410 }
411
412 int AUD_stop(AUD_Channel* handle)
413 {
414         if(AUD_device)
415                 return AUD_device->stop(handle);
416         return false;
417 }
418
419 int AUD_setKeep(AUD_Channel* handle, int keep)
420 {
421         assert(AUD_device);
422         return AUD_device->setKeep(handle, keep);
423 }
424
425 int AUD_seek(AUD_Channel* handle, float seekTo)
426 {
427         assert(AUD_device);
428         return AUD_device->seek(handle, seekTo);
429 }
430
431 float AUD_getPosition(AUD_Channel* handle)
432 {
433         assert(AUD_device);
434         return AUD_device->getPosition(handle);
435 }
436
437 AUD_Status AUD_getStatus(AUD_Channel* handle)
438 {
439         assert(AUD_device);
440         return AUD_device->getStatus(handle);
441 }
442
443 int AUD_setListenerLocation(const float* location)
444 {
445         assert(AUD_device);
446
447         if(AUD_3ddevice)
448         {
449                 AUD_Vector3 v(location[0], location[1], location[2]);
450                 AUD_3ddevice->setListenerLocation(v);
451                 return true;
452         }
453
454         return false;
455 }
456
457 int AUD_setListenerVelocity(const float* velocity)
458 {
459         assert(AUD_device);
460
461         if(AUD_3ddevice)
462         {
463                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
464                 AUD_3ddevice->setListenerVelocity(v);
465                 return true;
466         }
467
468         return false;
469 }
470
471 int AUD_setListenerOrientation(const float* orientation)
472 {
473         assert(AUD_device);
474
475         if(AUD_3ddevice)
476         {
477                 AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
478                 AUD_3ddevice->setListenerOrientation(q);
479                 return true;
480         }
481
482         return false;
483 }
484
485 int AUD_setSpeedOfSound(float speed)
486 {
487         assert(AUD_device);
488
489         if(AUD_3ddevice)
490         {
491                 AUD_3ddevice->setSpeedOfSound(speed);
492                 return true;
493         }
494
495         return false;
496 }
497
498 int AUD_setDopplerFactor(float factor)
499 {
500         assert(AUD_device);
501
502         if(AUD_3ddevice)
503         {
504                 AUD_3ddevice->setDopplerFactor(factor);
505                 return true;
506         }
507
508         return false;
509 }
510
511 int AUD_setDistanceModel(AUD_DistanceModel model)
512 {
513         assert(AUD_device);
514
515         if(AUD_3ddevice)
516         {
517                 AUD_3ddevice->setDistanceModel(model);
518                 return true;
519         }
520
521         return false;
522 }
523
524 int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
525 {
526         assert(AUD_device);
527         assert(handle);
528
529         if(AUD_3ddevice)
530         {
531                 AUD_Vector3 v(location[0], location[1], location[2]);
532                 return AUD_3ddevice->setSourceLocation(handle, v);
533         }
534
535         return false;
536 }
537
538 int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
539 {
540         assert(AUD_device);
541         assert(handle);
542
543         if(AUD_3ddevice)
544         {
545                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
546                 return AUD_3ddevice->setSourceVelocity(handle, v);
547         }
548
549         return false;
550 }
551
552 int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
553 {
554         assert(AUD_device);
555         assert(handle);
556
557         if(AUD_3ddevice)
558         {
559                 AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]);
560                 return AUD_3ddevice->setSourceOrientation(handle, q);
561         }
562
563         return false;
564 }
565
566 int AUD_setRelative(AUD_Channel* handle, int relative)
567 {
568         assert(AUD_device);
569         assert(handle);
570
571         if(AUD_3ddevice)
572         {
573                 return AUD_3ddevice->setRelative(handle, relative);
574         }
575
576         return false;
577 }
578
579 int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
580 {
581         assert(AUD_device);
582         assert(handle);
583
584         if(AUD_3ddevice)
585         {
586                 return AUD_3ddevice->setVolumeMaximum(handle, volume);
587         }
588
589         return false;
590 }
591
592 int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
593 {
594         assert(AUD_device);
595         assert(handle);
596
597         if(AUD_3ddevice)
598         {
599                 return AUD_3ddevice->setVolumeMinimum(handle, volume);
600         }
601
602         return false;
603 }
604
605 int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
606 {
607         assert(AUD_device);
608         assert(handle);
609
610         if(AUD_3ddevice)
611         {
612                 return AUD_3ddevice->setDistanceMaximum(handle, distance);
613         }
614
615         return false;
616 }
617
618 int AUD_setDistanceReference(AUD_Channel* handle, float distance)
619 {
620         assert(AUD_device);
621         assert(handle);
622
623         if(AUD_3ddevice)
624         {
625                 return AUD_3ddevice->setDistanceReference(handle, distance);
626         }
627
628         return false;
629 }
630
631 int AUD_setAttenuation(AUD_Channel* handle, float factor)
632 {
633         assert(AUD_device);
634         assert(handle);
635
636         if(AUD_3ddevice)
637         {
638                 return AUD_3ddevice->setAttenuation(handle, factor);
639         }
640
641         return false;
642 }
643
644 int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
645 {
646         assert(AUD_device);
647         assert(handle);
648
649         if(AUD_3ddevice)
650         {
651                 return AUD_3ddevice->setConeAngleOuter(handle, angle);
652         }
653
654         return false;
655 }
656
657 int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
658 {
659         assert(AUD_device);
660         assert(handle);
661
662         if(AUD_3ddevice)
663         {
664                 return AUD_3ddevice->setConeAngleInner(handle, angle);
665         }
666
667         return false;
668 }
669
670 int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
671 {
672         assert(AUD_device);
673         assert(handle);
674
675         if(AUD_3ddevice)
676         {
677                 return AUD_3ddevice->setConeVolumeOuter(handle, volume);
678         }
679
680         return false;
681 }
682
683 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
684 {
685         if(handle)
686         {
687                 assert(AUD_device);
688
689                 try
690                 {
691                         return AUD_device->setVolume(handle, volume);
692                 }
693                 catch(AUD_Exception&) {}
694         }
695         return false;
696 }
697
698 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
699 {
700         if(handle)
701         {
702                 assert(AUD_device);
703
704                 try
705                 {
706                         return AUD_device->setPitch(handle, pitch);
707                 }
708                 catch(AUD_Exception&) {}
709         }
710         return false;
711 }
712
713 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
714 {
715         try
716         {
717                 return new AUD_ReadDevice(specs);
718         }
719         catch(AUD_Exception&)
720         {
721                 return NULL;
722         }
723 }
724
725 AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
726 {
727         assert(device);
728         assert(sound);
729
730         try
731         {
732                 AUD_Channel* handle = device->play(sound);
733                 device->seek(handle, seek);
734                 return handle;
735         }
736         catch(AUD_Exception&)
737         {
738                 return NULL;
739         }
740 }
741
742 int AUD_setDeviceVolume(AUD_Device* device, float volume)
743 {
744         assert(device);
745
746         try
747         {
748                 device->setVolume(volume);
749                 return true;
750         }
751         catch(AUD_Exception&) {}
752         
753         return false;
754 }
755
756 int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
757                                                          float volume)
758 {
759         if(handle)
760         {
761                 assert(device);
762
763                 try
764                 {
765                         return device->setVolume(handle, volume);
766                 }
767                 catch(AUD_Exception&) {}
768         }
769         return false;
770 }
771
772 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
773 {
774         assert(device);
775         assert(buffer);
776
777         try
778         {
779                 return device->read(buffer, length);
780         }
781         catch(AUD_Exception&)
782         {
783                 return false;
784         }
785 }
786
787 void AUD_closeReadDevice(AUD_Device* device)
788 {
789         assert(device);
790
791         try
792         {
793                 delete device;
794         }
795         catch(AUD_Exception&)
796         {
797         }
798 }
799
800 float* AUD_readSoundBuffer(const char* filename, float low, float high,
801                                                    float attack, float release, float threshold,
802                                                    int accumulate, int additive, int square,
803                                                    float sthreshold, int samplerate, int* length)
804 {
805         AUD_Buffer buffer;
806         AUD_DeviceSpecs specs;
807         specs.channels = AUD_CHANNELS_MONO;
808         specs.rate = (AUD_SampleRate)samplerate;
809         AUD_Sound* sound;
810
811         AUD_FileFactory file(filename);
812         AUD_ChannelMapperFactory mapper(&file, specs);
813         AUD_LowpassFactory lowpass(&mapper, high);
814         AUD_HighpassFactory highpass(&lowpass, low);
815         AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
816         AUD_LinearResampleFactory resampler(&envelope, specs);
817         sound = &resampler;
818         AUD_SquareFactory squaref(sound, sthreshold);
819         if(square)
820                 sound = &squaref;
821         AUD_AccumulatorFactory accumulator(sound, additive);
822         AUD_SumFactory sum(sound);
823         if(accumulate)
824                 sound = &accumulator;
825         else if(additive)
826                 sound = &sum;
827
828         AUD_IReader* reader = sound->createReader();
829
830         if(reader == NULL)
831                 return NULL;
832
833         int len;
834         int position = 0;
835         sample_t* readbuffer;
836         do
837         {
838                 len = samplerate;
839                 buffer.resize((position + len) * sizeof(float), true);
840                 reader->read(len, readbuffer);
841                 memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
842                 position += len;
843         } while(len != 0);
844         delete reader;
845
846         float* result = (float*)malloc(position * sizeof(float));
847         memcpy(result, buffer.getBuffer(), position * sizeof(float));
848         *length = position;
849         return result;
850 }
851
852 static void pauseSound(AUD_Channel* handle)
853 {
854         assert(AUD_device);
855
856         AUD_device->pause(handle);
857 }
858
859 AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
860 {
861         assert(AUD_device);
862
863         AUD_SilenceFactory silence;
864         AUD_LimiterFactory limiter(&silence, 0, seconds);
865
866         try
867         {
868                 AUD_Channel* channel = AUD_device->play(&limiter);
869                 AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
870                 return channel;
871         }
872         catch(AUD_Exception&)
873         {
874                 return NULL;
875         }
876 }
877
878 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
879 {
880 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
881  * is initialized.
882
883         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
884 */
885         AUD_Specs specs;
886         specs.channels = AUD_CHANNELS_STEREO;
887         specs.rate = AUD_RATE_44100;
888         return new AUD_SequencerFactory(specs, data, volume);
889 }
890
891 void AUD_destroySequencer(AUD_Sound* sequencer)
892 {
893         delete ((AUD_SequencerFactory*)sequencer);
894 }
895
896 AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
897                                                                  float begin, float end, float skip, void* data)
898 {
899         return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
900 }
901
902 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
903 {
904         ((AUD_SequencerFactory*)sequencer)->remove(entry);
905 }
906
907 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
908                                    float begin, float end, float skip)
909 {
910         ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
911 }
912
913 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
914 {
915         ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
916 }
917
918 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
919 {
920         AUD_DeviceSpecs specs;
921         sample_t* buf;
922
923         specs.rate = AUD_RATE_INVALID;
924         specs.channels = AUD_CHANNELS_MONO;
925         specs.format = AUD_FORMAT_INVALID;
926
927         AUD_ChannelMapperFactory mapper(sound, specs);
928
929         AUD_IReader* reader = mapper.createReader();
930
931         int len = reader->getLength();
932         float samplejump = (float)len / (float)length;
933         float min, max;
934
935         for(int i = 0; i < length; i++)
936         {
937                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
938                 reader->read(len, buf);
939
940                 if(len < 1)
941                 {
942                         length = i;
943                         break;
944                 }
945
946                 max = min = *buf;
947                 for(int j = 1; j < len; j++)
948                 {
949                         if(buf[j] < min)
950                                 min = buf[j];
951                         if(buf[j] > max)
952                                 max = buf[j];
953                         buffer[i * 2] = min;
954                         buffer[i * 2 + 1] = max;
955                 }
956         }
957
958         delete reader;
959
960         return length;
961 }
962
963 void AUD_startPlayback()
964 {
965 #ifdef WITH_JACK
966         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
967         if(device)
968                 device->startPlayback();
969 #endif
970 }
971
972 void AUD_stopPlayback()
973 {
974 #ifdef WITH_JACK
975         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
976         if(device)
977                 device->stopPlayback();
978 #endif
979 }
980
981 void AUD_seekSequencer(AUD_Channel* handle, float time)
982 {
983 #ifdef WITH_JACK
984         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
985         if(device)
986                 device->seekPlayback(time);
987         else
988 #endif
989         {
990                 AUD_device->seek(handle, time);
991         }
992 }
993
994 float AUD_getSequencerPosition(AUD_Channel* handle)
995 {
996 #ifdef WITH_JACK
997         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
998         if(device)
999                 return device->getPlaybackPosition();
1000         else
1001 #endif
1002         {
1003                 return AUD_device->getPosition(handle);
1004         }
1005 }
1006
1007 #ifdef WITH_JACK
1008 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
1009 {
1010         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
1011         if(device)
1012                 device->setSyncCallback(function, data);
1013 }
1014 #endif
1015
1016 int AUD_doesPlayback()
1017 {
1018 #ifdef WITH_JACK
1019         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
1020         if(device)
1021                 return device->doesPlayback();
1022 #endif
1023         return -1;
1024 }