Audaspace: HUGE Refactor.
[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 #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_SourceCaps.h"
62 #include "AUD_IReader.h"
63 #include "AUD_SequencerFactory.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(specs, buffersize);
135                         break;
136 #endif
137                 default:
138                         return false;
139                 }
140
141                 AUD_device = dev;
142                 if(AUD_device->checkCapability(AUD_CAPS_3D_DEVICE))
143                         AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
144
145 #ifdef WITH_PYTHON
146                 if(g_pyinitialized)
147                 {
148                         g_device = (Device*)Device_empty();
149                         if(g_device != NULL)
150                         {
151                                 g_device->device = dev;
152                         }
153                 }
154 #endif
155
156                 return true;
157         }
158         catch(AUD_Exception&)
159         {
160                 return false;
161         }
162 }
163
164 int* AUD_enumDevices()
165 {
166         int i = 0;
167 #ifdef WITH_SDL
168         AUD_available_devices[i++] = AUD_SDL_DEVICE;
169 #endif
170 #ifdef WITH_OPENAL
171         AUD_available_devices[i++] = AUD_OPENAL_DEVICE;
172 #endif
173 #ifdef WITH_JACK
174         AUD_available_devices[i++] = AUD_JACK_DEVICE;
175 #endif
176         AUD_available_devices[i++] = AUD_NULL_DEVICE;
177         return AUD_available_devices;
178 }
179
180 void AUD_exit()
181 {
182 #ifdef WITH_PYTHON
183         if(g_device)
184         {
185                 Py_XDECREF(g_device);
186                 g_device = NULL;
187         }
188         else
189 #endif
190         if(AUD_device)
191                 delete AUD_device;
192         AUD_device = NULL;
193         AUD_3ddevice = NULL;
194 }
195
196 #ifdef WITH_PYTHON
197 static PyObject* AUD_getCDevice(PyObject* self)
198 {
199         if(g_device)
200         {
201                 Py_INCREF(g_device);
202                 return (PyObject*)g_device;
203         }
204         Py_RETURN_NONE;
205 }
206
207 static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS,
208                                                                                   "device()\n\n"
209                                                                                   "Returns the application's Device.\n\n"
210                                                                                   ":return: The application's Device.\n"
211                                                                                   ":rtype: aud.Device"}};
212
213 PyObject* AUD_initPython()
214 {
215         PyObject* module = PyInit_aud();
216         PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL));
217         PyDict_SetItemString(PySys_GetObject("modules"), "aud", module);
218         if(AUD_device)
219         {
220                 g_device = (Device*)Device_empty();
221                 if(g_device != NULL)
222                 {
223                         g_device->device = AUD_device;
224                 }
225         }
226         g_pyinitialized = true;
227
228         return module;
229 }
230 #endif
231
232 void AUD_lock()
233 {
234         assert(AUD_device);
235         AUD_device->lock();
236 }
237
238 void AUD_unlock()
239 {
240         assert(AUD_device);
241         AUD_device->unlock();
242 }
243
244 AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
245 {
246         assert(sound);
247
248         AUD_IReader* reader = sound->createReader();
249
250         AUD_SoundInfo info;
251
252         if(reader)
253         {
254                 info.specs = reader->getSpecs();
255                 info.length = reader->getLength() / (float) info.specs.rate;
256         }
257         else
258         {
259                 info.specs.channels = AUD_CHANNELS_INVALID;
260                 info.specs.rate = AUD_RATE_INVALID;
261                 info.length = 0.0f;
262         }
263
264         return info;
265 }
266
267 AUD_Sound* AUD_load(const char* filename)
268 {
269         assert(filename);
270         return new AUD_FileFactory(filename);
271 }
272
273 AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size)
274 {
275         assert(buffer);
276         return new AUD_FileFactory(buffer, size);
277 }
278
279 AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
280 {
281         assert(sound);
282
283         try
284         {
285                 return new AUD_StreamBufferFactory(sound);
286         }
287         catch(AUD_Exception&)
288         {
289                 return NULL;
290         }
291 }
292
293 AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
294 {
295         assert(sound);
296
297         try
298         {
299                 return new AUD_DelayFactory(sound, delay);
300         }
301         catch(AUD_Exception&)
302         {
303                 return NULL;
304         }
305 }
306
307 AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
308 {
309         assert(sound);
310
311         try
312         {
313                 return new AUD_LimiterFactory(sound, start, end);
314         }
315         catch(AUD_Exception&)
316         {
317                 return NULL;
318         }
319 }
320
321 AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
322 {
323         assert(sound);
324
325         try
326         {
327                 return new AUD_PingPongFactory(sound);
328         }
329         catch(AUD_Exception&)
330         {
331                 return NULL;
332         }
333 }
334
335 AUD_Sound* AUD_loopSound(AUD_Sound* sound)
336 {
337         assert(sound);
338
339         try
340         {
341                 return new AUD_LoopFactory(sound);
342         }
343         catch(AUD_Exception&)
344         {
345                 return NULL;
346         }
347 }
348
349 int AUD_setLoop(AUD_Channel* handle, int loops, float time)
350 {
351         if(handle)
352         {
353                 /* AUD_XXX Doesn't work atm, will come back
354
355                 AUD_Message message;
356                 message.type = AUD_MSG_LOOP;
357                 message.loopcount = loops;
358                 message.time = time;
359
360                 try
361                 {
362                         return AUD_device->sendMessage(handle, message);
363                 }
364                 catch(AUD_Exception&)
365                 {
366                 }*/
367         }
368         return false;
369 }
370
371 AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
372 {
373         assert(sound);
374
375         try
376         {
377                 return new AUD_RectifyFactory(sound);
378         }
379         catch(AUD_Exception&)
380         {
381                 return NULL;
382         }
383 }
384
385 void AUD_unload(AUD_Sound* sound)
386 {
387         assert(sound);
388         delete sound;
389 }
390
391 AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
392 {
393         assert(AUD_device);
394         assert(sound);
395         try
396         {
397                 return AUD_device->play(sound, keep);
398         }
399         catch(AUD_Exception&)
400         {
401                 return NULL;
402         }
403 }
404
405 int AUD_pause(AUD_Channel* handle)
406 {
407         assert(AUD_device);
408         return AUD_device->pause(handle);
409 }
410
411 int AUD_resume(AUD_Channel* handle)
412 {
413         assert(AUD_device);
414         return AUD_device->resume(handle);
415 }
416
417 int AUD_stop(AUD_Channel* handle)
418 {
419         if(AUD_device)
420                 return AUD_device->stop(handle);
421         return false;
422 }
423
424 int AUD_setKeep(AUD_Channel* handle, int keep)
425 {
426         assert(AUD_device);
427         return AUD_device->setKeep(handle, keep);
428 }
429
430 int AUD_seek(AUD_Channel* handle, float seekTo)
431 {
432         assert(AUD_device);
433         return AUD_device->seek(handle, seekTo);
434 }
435
436 float AUD_getPosition(AUD_Channel* handle)
437 {
438         assert(AUD_device);
439         return AUD_device->getPosition(handle);
440 }
441
442 AUD_Status AUD_getStatus(AUD_Channel* handle)
443 {
444         assert(AUD_device);
445         return AUD_device->getStatus(handle);
446 }
447
448 AUD_Channel* AUD_play3D(AUD_Sound* sound, int keep)
449 {
450         assert(AUD_device);
451         assert(sound);
452
453         try
454         {
455                 if(AUD_3ddevice)
456                         return AUD_3ddevice->play3D(sound, keep);
457                 else
458                         return AUD_device->play(sound, keep);
459         }
460         catch(AUD_Exception&)
461         {
462                 return NULL;
463         }
464 }
465
466 int AUD_updateListener(AUD_3DData* data)
467 {
468         assert(AUD_device);
469         assert(data);
470
471         try
472         {
473                 if(AUD_3ddevice)
474                         return AUD_3ddevice->updateListener(*data);
475         }
476         catch(AUD_Exception&)
477         {
478         }
479         return false;
480 }
481
482 int AUD_set3DSetting(AUD_3DSetting setting, float value)
483 {
484         assert(AUD_device);
485
486         try
487         {
488                 if(AUD_3ddevice)
489                         return AUD_3ddevice->setSetting(setting, value);
490         }
491         catch(AUD_Exception&)
492         {
493         }
494         return false;
495 }
496
497 float AUD_get3DSetting(AUD_3DSetting setting)
498 {
499         assert(AUD_device);
500
501         try
502         {
503                 if(AUD_3ddevice)
504                         return AUD_3ddevice->getSetting(setting);
505         }
506         catch(AUD_Exception&)
507         {
508         }
509         return 0.0f;
510 }
511
512 int AUD_update3DSource(AUD_Channel* handle, AUD_3DData* data)
513 {
514         if(handle)
515         {
516                 assert(AUD_device);
517                 assert(data);
518
519                 try
520                 {
521                         if(AUD_3ddevice)
522                                 return AUD_3ddevice->updateSource(handle, *data);
523                 }
524                 catch(AUD_Exception&)
525                 {
526                 }
527         }
528         return false;
529 }
530
531 int AUD_set3DSourceSetting(AUD_Channel* handle,
532                                                    AUD_3DSourceSetting setting, float value)
533 {
534         if(handle)
535         {
536                 assert(AUD_device);
537
538                 try
539                 {
540                         if(AUD_3ddevice)
541                                 return AUD_3ddevice->setSourceSetting(handle, setting, value);
542                 }
543                 catch(AUD_Exception&)
544                 {
545                 }
546         }
547         return false;
548 }
549
550 float AUD_get3DSourceSetting(AUD_Channel* handle, AUD_3DSourceSetting setting)
551 {
552         if(handle)
553         {
554                 assert(AUD_device);
555
556                 try
557                 {
558                         if(AUD_3ddevice)
559                                 return AUD_3ddevice->getSourceSetting(handle, setting);
560                 }
561                 catch(AUD_Exception&)
562                 {
563                 }
564         }
565         return 0.0f;
566 }
567
568 int AUD_setSoundVolume(AUD_Channel* handle, float volume)
569 {
570         if(handle)
571         {
572                 assert(AUD_device);
573                 AUD_SourceCaps caps;
574                 caps.handle = handle;
575                 caps.value = volume;
576
577                 try
578                 {
579                         return AUD_device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
580                 }
581                 catch(AUD_Exception&) {}
582         }
583         return false;
584 }
585
586 int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
587 {
588         if(handle)
589         {
590                 assert(AUD_device);
591                 AUD_SourceCaps caps;
592                 caps.handle = handle;
593                 caps.value = pitch;
594
595                 try
596                 {
597                         return AUD_device->setCapability(AUD_CAPS_SOURCE_PITCH, &caps);
598                 }
599                 catch(AUD_Exception&) {}
600         }
601         return false;
602 }
603
604 AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
605 {
606         try
607         {
608                 return new AUD_ReadDevice(specs);
609         }
610         catch(AUD_Exception&)
611         {
612                 return NULL;
613         }
614 }
615
616 AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
617 {
618         assert(device);
619         assert(sound);
620
621         try
622         {
623                 AUD_Channel* handle = device->play(sound);
624                 device->seek(handle, seek);
625                 return handle;
626         }
627         catch(AUD_Exception&)
628         {
629                 return NULL;
630         }
631 }
632
633 int AUD_setDeviceVolume(AUD_Device* device, float volume)
634 {
635         assert(device);
636
637         try
638         {
639                 return device->setCapability(AUD_CAPS_VOLUME, &volume);
640         }
641         catch(AUD_Exception&) {}
642         
643         return false;
644 }
645
646 int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
647                                                          float volume)
648 {
649         if(handle)
650         {
651                 assert(device);
652                 AUD_SourceCaps caps;
653                 caps.handle = handle;
654                 caps.value = volume;
655
656                 try
657                 {
658                         return device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
659                 }
660                 catch(AUD_Exception&) {}
661         }
662         return false;
663 }
664
665 int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
666 {
667         assert(device);
668         assert(buffer);
669
670         try
671         {
672                 return device->read(buffer, length);
673         }
674         catch(AUD_Exception&)
675         {
676                 return false;
677         }
678 }
679
680 void AUD_closeReadDevice(AUD_Device* device)
681 {
682         assert(device);
683
684         try
685         {
686                 delete device;
687         }
688         catch(AUD_Exception&)
689         {
690         }
691 }
692
693 float* AUD_readSoundBuffer(const char* filename, float low, float high,
694                                                    float attack, float release, float threshold,
695                                                    int accumulate, int additive, int square,
696                                                    float sthreshold, int samplerate, int* length)
697 {
698         AUD_Buffer buffer;
699         AUD_DeviceSpecs specs;
700         specs.channels = AUD_CHANNELS_MONO;
701         specs.rate = (AUD_SampleRate)samplerate;
702         AUD_Sound* sound;
703
704         AUD_FileFactory file(filename);
705         AUD_ChannelMapperFactory mapper(&file, specs);
706         AUD_LowpassFactory lowpass(&mapper, high);
707         AUD_HighpassFactory highpass(&lowpass, low);
708         AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
709         AUD_LinearResampleFactory resampler(&envelope, specs);
710         sound = &resampler;
711         AUD_SquareFactory squaref(sound, sthreshold);
712         if(square)
713                 sound = &squaref;
714         AUD_AccumulatorFactory accumulator(sound, additive);
715         AUD_SumFactory sum(sound);
716         if(accumulate)
717                 sound = &accumulator;
718         else if(additive)
719                 sound = &sum;
720
721         AUD_IReader* reader = sound->createReader();
722
723         if(reader == NULL)
724                 return NULL;
725
726         int len;
727         int position = 0;
728         sample_t* readbuffer;
729         do
730         {
731                 len = samplerate;
732                 buffer.resize((position + len) * sizeof(float), true);
733                 reader->read(len, readbuffer);
734                 memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
735                 position += len;
736         } while(len != 0);
737         delete reader;
738
739         float* result = (float*)malloc(position * sizeof(float));
740         memcpy(result, buffer.getBuffer(), position * sizeof(float));
741         *length = position;
742         return result;
743 }
744
745 AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
746 {
747 /* AUD_XXX should be this: but AUD_createSequencer is called before the device
748  * is initialized.
749
750         return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume);
751 */
752         AUD_Specs specs;
753         specs.channels = AUD_CHANNELS_STEREO;
754         specs.rate = AUD_RATE_44100;
755         return new AUD_SequencerFactory(specs, data, volume);
756 }
757
758 void AUD_destroySequencer(AUD_Sound* sequencer)
759 {
760         delete ((AUD_SequencerFactory*)sequencer);
761 }
762
763 AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
764                                                                  float begin, float end, float skip, void* data)
765 {
766         return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data);
767 }
768
769 void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry)
770 {
771         ((AUD_SequencerFactory*)sequencer)->remove(entry);
772 }
773
774 void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
775                                    float begin, float end, float skip)
776 {
777         ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip);
778 }
779
780 void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute)
781 {
782         ((AUD_SequencerFactory*)sequencer)->mute(entry, mute);
783 }
784
785 int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
786 {
787         AUD_DeviceSpecs specs;
788         sample_t* buf;
789
790         specs.rate = AUD_RATE_INVALID;
791         specs.channels = AUD_CHANNELS_MONO;
792         specs.format = AUD_FORMAT_INVALID;
793
794         AUD_ChannelMapperFactory mapper(sound, specs);
795
796         AUD_IReader* reader = mapper.createReader();
797
798         int len = reader->getLength();
799         float samplejump = (float)len / (float)length;
800         float min, max;
801
802         for(int i = 0; i < length; i++)
803         {
804                 len = floor(samplejump * (i+1)) - floor(samplejump * i);
805                 reader->read(len, buf);
806
807                 if(len < 1)
808                 {
809                         length = i;
810                         break;
811                 }
812
813                 max = min = *buf;
814                 for(int j = 1; j < len; j++)
815                 {
816                         if(buf[j] < min)
817                                 min = buf[j];
818                         if(buf[j] > max)
819                                 max = buf[j];
820                         buffer[i * 2] = min;
821                         buffer[i * 2 + 1] = max;
822                 }
823         }
824
825         delete reader;
826
827         return length;
828 }
829
830 void AUD_startPlayback()
831 {
832 #ifdef WITH_JACK
833         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
834         if(device)
835                 device->startPlayback();
836 #endif
837 }
838
839 void AUD_stopPlayback()
840 {
841 #ifdef WITH_JACK
842         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
843         if(device)
844                 device->stopPlayback();
845 #endif
846 }
847
848 void AUD_seekSequencer(AUD_Channel* handle, float time)
849 {
850 #ifdef WITH_JACK
851         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
852         if(device)
853                 device->seekPlayback(time);
854         else
855 #endif
856         {
857                 AUD_device->seek(handle, time);
858         }
859 }
860
861 float AUD_getSequencerPosition(AUD_Channel* handle)
862 {
863 #ifdef WITH_JACK
864         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
865         if(device)
866                 return device->getPlaybackPosition();
867         else
868 #endif
869         {
870                 return AUD_device->getPosition(handle);
871         }
872 }
873
874 #ifdef WITH_JACK
875 void AUD_setSyncCallback(AUD_syncFunction function, void* data)
876 {
877         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
878         if(device)
879                 device->setSyncCallback(function, data);
880 }
881 #endif
882
883 int AUD_doesPlayback()
884 {
885 #ifdef WITH_JACK
886         AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
887         if(device)
888                 return device->doesPlayback();
889 #endif
890         return -1;
891 }