40cbbd92d93c97885adac8e5b59d19b561761d64
[blender-staging.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 #include <cstdlib>
34 #include <cstring>
35 #include <cmath>
36
37 #ifndef __STDC_CONSTANT_MACROS
38 // needed for INT64_C
39 #define __STDC_CONSTANT_MACROS
40 #endif
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_IReader* reader = sound->createReader();
248
249         AUD_SoundInfo info;
250
251         if(reader)
252         {
253                 info.specs = reader->getSpecs();
254                 info.length = reader->getLength() / (float) info.specs.rate;
255         }
256         else
257         {
258                 info.specs.channels = AUD_CHANNELS_INVALID;
259                 info.specs.rate = AUD_RATE_INVALID;
260                 info.length = 0.0f;
261         }
262
263         return info;
264 }
265
266 AUD_Sound* AUD_load(const char* filename)
267 {
268         assert(filename);
269         return new AUD_FileFactory(filename);
270 }
271
272 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
273 {
274         assert(buffer);
275         return new AUD_FileFactory(buffer, size);
276 }
277
278 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
279 {
280         assert(sound);
281
282         try
283         {
284                 return new AUD_StreamBufferFactory(sound);
285         }
286         catch(AUD_Exception&)
287         {
288                 return NULL;
289         }
290 }
291
292 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
293 {
294         assert(sound);
295
296         try
297         {
298                 return new AUD_DelayFactory(sound, delay);
299         }
300         catch(AUD_Exception&)
301         {
302                 return NULL;
303         }
304 }
305
306 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
307 {
308         assert(sound);
309
310         try
311         {
312                 return new AUD_LimiterFactory(sound, start, end);
313         }
314         catch(AUD_Exception&)
315         {
316                 return NULL;
317         }
318 }
319
320 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
321 {
322         assert(sound);
323
324         try
325         {
326                 return new AUD_PingPongFactory(sound);
327         }
328         catch(AUD_Exception&)
329         {
330                 return NULL;
331         }
332 }
333
334 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
335 {
336         assert(sound);
337
338         try
339         {
340                 return new AUD_LoopFactory(sound);
341         }
342         catch(AUD_Exception&)
343         {
344                 return NULL;
345         }
346 }
347
348 int AUD_setLoop(AUD_Channel* handle, int loops)
349 {
350         if(handle)
351         {
352                 try
353                 {
354                         return AUD_device->setLoopCount(handle, loops);
355                 }
356                 catch(AUD_Exception&)
357                 {
358                 }
359         }
360         return false;
361 }
362
363 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
364 {
365         assert(sound);
366
367         try
368         {
369                 return new AUD_RectifyFactory(sound);
370         }
371         catch(AUD_Exception&)
372         {
373                 return NULL;
374         }
375 }
376
377 void AUD_unload(AUD_Sound* sound)
378 {
379         assert(sound);
380         delete sound;
381 }
382
383 AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
384 {
385         assert(AUD_device);
386         assert(sound);
387         try
388         {
389                 return AUD_device->play(sound, keep);
390         }
391         catch(AUD_Exception&)
392         {
393                 return NULL;
394         }
395 }
396
397 int AUD_pause(AUD_Channel* handle)
398 {
399         assert(AUD_device);
400         return AUD_device->pause(handle);
401 }
402
403 int AUD_resume(AUD_Channel* handle)
404 {
405         assert(AUD_device);
406         return AUD_device->resume(handle);
407 }
408
409 int AUD_stop(AUD_Channel* handle)
410 {
411         if(AUD_device)
412                 return AUD_device->stop(handle);
413         return false;
414 }
415
416 int AUD_setKeep(AUD_Channel* handle, int keep)
417 {
418         assert(AUD_device);
419         return AUD_device->setKeep(handle, keep);
420 }
421
422 int AUD_seek(AUD_Channel* handle, float seekTo)
423 {
424         assert(AUD_device);
425         return AUD_device->seek(handle, seekTo);
426 }
427
428 float AUD_getPosition(AUD_Channel* handle)
429 {
430         assert(AUD_device);
431         return AUD_device->getPosition(handle);
432 }
433
434 AUD_Status AUD_getStatus(AUD_Channel* handle)
435 {
436         assert(AUD_device);
437         return AUD_device->getStatus(handle);
438 }
439
440 int AUD_setListenerLocation(const float* location)
441 {
442         assert(AUD_device);
443
444         if(AUD_3ddevice)
445         {
446                 AUD_Vector3 v(location[0], location[1], location[2]);
447                 AUD_3ddevice->setListenerLocation(v);
448                 return true;
449         }
450
451         return false;
452 }
453
454 int AUD_setListenerVelocity(const float* velocity)
455 {
456         assert(AUD_device);
457
458         if(AUD_3ddevice)
459         {
460                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
461                 AUD_3ddevice->setListenerVelocity(v);
462                 return true;
463         }
464
465         return false;
466 }
467
468 int AUD_setListenerOrientation(const float* orientation)
469 {
470         assert(AUD_device);
471
472         if(AUD_3ddevice)
473         {
474                 AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
475                 AUD_3ddevice->setListenerOrientation(q);
476                 return true;
477         }
478
479         return false;
480 }
481
482 int AUD_setSpeedOfSound(float speed)
483 {
484         assert(AUD_device);
485
486         if(AUD_3ddevice)
487         {
488                 AUD_3ddevice->setSpeedOfSound(speed);
489                 return true;
490         }
491
492         return false;
493 }
494
495 int AUD_setDopplerFactor(float factor)
496 {
497         assert(AUD_device);
498
499         if(AUD_3ddevice)
500         {
501                 AUD_3ddevice->setDopplerFactor(factor);
502                 return true;
503         }
504
505         return false;
506 }
507
508 int AUD_setDistanceModel(AUD_DistanceModel model)
509 {
510         assert(AUD_device);
511
512         if(AUD_3ddevice)
513         {
514                 AUD_3ddevice->setDistanceModel(model);
515                 return true;
516         }
517
518         return false;
519 }
520
521 int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
522 {
523         assert(AUD_device);
524         assert(handle);
525
526         if(AUD_3ddevice)
527         {
528                 AUD_Vector3 v(location[0], location[1], location[2]);
529                 return AUD_3ddevice->setSourceLocation(handle, v);
530         }
531
532         return false;
533 }
534
535 int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
536 {
537         assert(AUD_device);
538         assert(handle);
539
540         if(AUD_3ddevice)
541         {
542                 AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
543                 return AUD_3ddevice->setSourceVelocity(handle, v);
544         }
545
546         return false;
547 }
548
549 int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
550 {
551         assert(AUD_device);
552         assert(handle);
553
554         if(AUD_3ddevice)
555         {
556                 AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
557                 return AUD_3ddevice->setSourceOrientation(handle, q);
558         }
559
560         return false;
561 }
562
563 int AUD_setRelative(AUD_Channel* handle, int relative)
564 {
565         assert(AUD_device);
566         assert(handle);
567
568         if(AUD_3ddevice)
569         {
570                 return AUD_3ddevice->setRelative(handle, relative);
571         }
572
573         return false;
574 }
575
576 int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
577 {
578         assert(AUD_device);
579         assert(handle);
580
581         if(AUD_3ddevice)
582         {
583                 return AUD_3ddevice->setVolumeMaximum(handle, volume);
584         }
585
586         return false;
587 }
588
589 int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
590 {
591         assert(AUD_device);
592         assert(handle);
593
594         if(AUD_3ddevice)
595         {
596                 return AUD_3ddevice->setVolumeMinimum(handle, volume);
597         }
598
599         return false;
600 }
601
602 int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
603 {
604         assert(AUD_device);
605         assert(handle);
606
607         if(AUD_3ddevice)
608         {
609                 return AUD_3ddevice->setDistanceMaximum(handle, distance);
610         }
611
612         return false;
613 }
614
615 int AUD_setDistanceReference(AUD_Channel* handle, float distance)
616 {
617         assert(AUD_device);
618         assert(handle);
619
620         if(AUD_3ddevice)
621         {
622                 return AUD_3ddevice->setDistanceReference(handle, distance);
623         }
624
625         return false;
626 }
627
628 int AUD_setAttenuation(AUD_Channel* handle, float factor)
629 {
630         assert(AUD_device);
631         assert(handle);
632
633         if(AUD_3ddevice)
634         {
635                 return AUD_3ddevice->setAttenuation(handle, factor);
636         }
637
638         return false;
639 }
640
641 int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
642 {
643         assert(AUD_device);
644         assert(handle);
645
646         if(AUD_3ddevice)
647         {
648                 return AUD_3ddevice->setConeAngleOuter(handle, angle);
649         }
650
651         return false;
652 }
653
654 int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
655 {
656         assert(AUD_device);
657         assert(handle);
658
659         if(AUD_3ddevice)
660         {
661                 return AUD_3ddevice->setConeAngleInner(handle, angle);
662         }
663
664         return false;
665 }
666
667 int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
668 {
669         assert(AUD_device);
670         assert(handle);
671
672         if(AUD_3ddevice)
673         {
674                 return AUD_3ddevice->setConeVolumeOuter(handle, volume);
675         }
676
677         return false;
678 }
679
680 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
681 {
682         if(handle)
683         {
684                 assert(AUD_device);
685
686                 try
687                 {
688                         return AUD_device->setVolume(handle, volume);
689                 }
690                 catch(AUD_Exception&) {}
691         }
692         return false;
693 }
694
695 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
696 {
697         if(handle)
698         {
699                 assert(AUD_device);
700
701                 try
702                 {
703                         return AUD_device->setPitch(handle, pitch);
704                 }
705                 catch(AUD_Exception&) {}
706         }
707         return false;
708 }
709
710 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
711 {
712         try
713         {
714                 return new AUD_ReadDevice(specs);
715         }
716         catch(AUD_Exception&)
717         {
718                 return NULL;
719         }
720 }
721
722 AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
723 {
724         assert(device);
725         assert(sound);
726
727         try
728         {
729                 AUD_Channel* handle = device->play(sound);
730                 device->seek(handle, seek);
731                 return handle;
732         }
733         catch(AUD_Exception&)
734         {
735                 return NULL;
736         }
737 }
738
739 int AUD_setDeviceVolume(AUD_Device* device, float volume)
740 {
741         assert(device);
742
743         try
744         {
745                 device->setVolume(volume);
746                 return true;
747         }
748         catch(AUD_Exception&) {}
749         
750         return false;
751 }
752
753 int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
754                                                          float volume)
755 {
756         if(handle)
757         {
758                 assert(device);
759
760                 try
761                 {
762                         return device->setVolume(handle, volume);
763                 }
764                 catch(AUD_Exception&) {}
765         }
766         return false;
767 }
768
769 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
770 {
771         assert(device);
772         assert(buffer);
773
774         try
775         {
776                 return device->read(buffer, length);
777         }
778         catch(AUD_Exception&)
779         {
780                 return false;
781         }
782 }
783
784 void AUD_closeReadDevice(AUD_Device* device)
785 {
786         assert(device);
787
788         try
789         {
790                 delete device;
791         }
792         catch(AUD_Exception&)
793         {
794         }
795 }
796
797 float* AUD_readSoundBuffer(const char* filename, float low, float high,
798                                                    float attack, float release, float threshold,
799                                                    int accumulate, int additive, int square,
800                                                    float sthreshold, int samplerate, int* length)
801 {
802         AUD_Buffer buffer;
803         AUD_DeviceSpecs specs;
804         specs.channels = AUD_CHANNELS_MONO;
805         specs.rate = (AUD_SampleRate)samplerate;
806         AUD_Sound* sound;
807
808         AUD_FileFactory file(filename);
809         AUD_ChannelMapperFactory mapper(&file, specs);
810         AUD_LowpassFactory lowpass(&mapper, high);
811         AUD_HighpassFactory highpass(&lowpass, low);
812         AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
813         AUD_LinearResampleFactory resampler(&envelope, specs);
814         sound = &resampler;
815         AUD_SquareFactory squaref(sound, sthreshold);
816         if(square)
817                 sound = &squaref;
818         AUD_AccumulatorFactory accumulator(sound, additive);
819         AUD_SumFactory sum(sound);
820         if(accumulate)
821                 sound = &accumulator;
822         else if(additive)
823                 sound = &sum;
824
825         AUD_IReader* reader = sound->createReader();
826
827         if(reader == NULL)
828                 return NULL;
829
830         int len;
831         int position = 0;
832         sample_t* readbuffer;
833         do
834         {
835                 len = samplerate;
836                 buffer.resize((position + len) * sizeof(float), true);
837                 reader->read(len, readbuffer);
838                 memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
839                 position += len;
840         } while(len != 0);
841         delete reader;
842
843         float* result = (float*)malloc(position * sizeof(float));
844         memcpy(result, buffer.getBuffer(), position * sizeof(float));
845         *length = position;
846         return result;
847 }
848
849 static void pauseSound(AUD_Channel* handle)
850 {
851         assert(AUD_device);
852
853         AUD_device->pause(handle);
854 }
855
856 AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
857 {
858         assert(AUD_device);
859
860         AUD_SilenceFactory silence;
861         AUD_LimiterFactory limiter(&silence, 0, seconds);
862
863         try
864         {
865                 AUD_Channel* channel = AUD_device->play(&limiter);
866                 AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
867                 return channel;
868         }
869         catch(AUD_Exception&)
870         {
871                 return NULL;
872         }
873 }
874
875 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
876 {
877 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
878  * is initialized.
879
880         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
881 */
882         AUD_Specs specs;
883         specs.channels = AUD_CHANNELS_STEREO;
884         specs.rate = AUD_RATE_44100;
885         return new AUD_SequencerFactory(specs, data, volume);
886 }
887
888 void AUD_destroySequencer(AUD_Sound* sequencer)
889 {
890         delete ((AUD_SequencerFactory*)sequencer);
891 }
892
893 AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
894                                                                  float begin, float end, float skip, void* data)
895 {
896         return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
897 }
898
899 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
900 {
901         ((AUD_SequencerFactory*)sequencer)->remove(entry);
902 }
903
904 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
905                                    float begin, float end, float skip)
906 {
907         ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
908 }
909
910 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
911 {
912         ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
913 }
914
915 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
916 {
917         AUD_DeviceSpecs specs;
918         sample_t* buf;
919
920         specs.rate = AUD_RATE_INVALID;
921         specs.channels = AUD_CHANNELS_MONO;
922         specs.format = AUD_FORMAT_INVALID;
923
924         AUD_ChannelMapperFactory mapper(sound, specs);
925
926         AUD_IReader* reader = mapper.createReader();
927
928         int len = reader->getLength();
929         float samplejump = (float)len / (float)length;
930         float min, max;
931
932         for(int i = 0; i < length; i++)
933         {
934                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
935                 reader->read(len, buf);
936
937                 if(len < 1)
938                 {
939                         length = i;
940                         break;
941                 }
942
943                 max = min = *buf;
944                 for(int j = 1; j < len; j++)
945                 {
946                         if(buf[j] < min)
947                                 min = buf[j];
948                         if(buf[j] > max)
949                                 max = buf[j];
950                         buffer[i * 2] = min;
951                         buffer[i * 2 + 1] = max;
952                 }
953         }
954
955         delete reader;
956
957         return length;
958 }
959
960 void AUD_startPlayback()
961 {
962 #ifdef WITH_JACK
963         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
964         if(device)
965                 device->startPlayback();
966 #endif
967 }
968
969 void AUD_stopPlayback()
970 {
971 #ifdef WITH_JACK
972         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
973         if(device)
974                 device->stopPlayback();
975 #endif
976 }
977
978 void AUD_seekSequencer(AUD_Channel* handle, float time)
979 {
980 #ifdef WITH_JACK
981         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
982         if(device)
983                 device->seekPlayback(time);
984         else
985 #endif
986         {
987                 AUD_device->seek(handle, time);
988         }
989 }
990
991 float AUD_getSequencerPosition(AUD_Channel* handle)
992 {
993 #ifdef WITH_JACK
994         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
995         if(device)
996                 return device->getPlaybackPosition();
997         else
998 #endif
999         {
1000                 return AUD_device->getPosition(handle);
1001         }
1002 }
1003
1004 #ifdef WITH_JACK
1005 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
1006 {
1007         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
1008         if(device)
1009                 device->setSyncCallback(function, data);
1010 }
1011 #endif
1012
1013 int AUD_doesPlayback()
1014 {
1015 #ifdef WITH_JACK
1016         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
1017         if(device)
1018                 return device->doesPlayback();
1019 #endif
1020         return -1;
1021 }