tmp
[blender.git] / extern / audaspace / bindings / python / PySound.cpp
1 /*******************************************************************************
2  * Copyright 2009-2016 Jörg Müller
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16
17 #include "PySound.h"
18 #include "PySource.h"
19 #include "PyThreadPool.h"
20
21 #ifdef WITH_CONVOLUTION
22 #include "PyHRTF.h"
23 #include "PyImpulseResponse.h"
24 #endif
25
26 #include "Exception.h"
27 #include "file/File.h"
28 #include "file/FileWriter.h"
29 #include "util/StreamBuffer.h"
30 #include "generator/Sawtooth.h"
31 #include "generator/Silence.h"
32 #include "generator/Sine.h"
33 #include "generator/Square.h"
34 #include "generator/Triangle.h"
35 #include "fx/Accumulator.h"
36 #include "fx/ADSR.h"
37 #include "fx/Delay.h"
38 #include "fx/Envelope.h"
39 #include "fx/Fader.h"
40 #include "fx/Highpass.h"
41 #include "fx/IIRFilter.h"
42 #include "fx/Limiter.h"
43 #include "fx/Loop.h"
44 #include "fx/Lowpass.h"
45 #include "fx/MutableSound.h"
46 #include "fx/Pitch.h"
47 #include "fx/Reverse.h"
48 #include "fx/SoundList.h"
49 #include "fx/Sum.h"
50 #include "fx/Threshold.h"
51 #include "fx/Volume.h"
52 #include "respec/ChannelMapper.h"
53 #include "respec/ChannelMapperReader.h"
54 #include "respec/LinearResample.h"
55 #include "respec/JOSResample.h"
56 #include "respec/JOSResampleReader.h"
57 #include "sequence/Double.h"
58 #include "sequence/PingPong.h"
59 #include "sequence/Superpose.h"
60
61 #ifdef WITH_CONVOLUTION
62 #include "fx/BinauralSound.h"
63 #include "fx/ConvolverSound.h"
64 #endif
65
66 #include <cstring>
67 #include <structmember.h>
68 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
69 #include <numpy/ndarrayobject.h>
70
71 using namespace aud;
72
73 extern PyObject* AUDError;
74
75 static void
76 Sound_dealloc(Sound* self)
77 {
78         if(self->sound)
79                 delete reinterpret_cast<std::shared_ptr<ISound>*>(self->sound);
80         Py_TYPE(self)->tp_free((PyObject *)self);
81 }
82
83 static PyObject *
84 Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
85 {
86         Sound* self;
87
88         self = (Sound*)type->tp_alloc(type, 0);
89         if(self != nullptr)
90         {
91                 static const char* kwlist[] = {"filename", nullptr};
92                 const char* filename = nullptr;
93
94                 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Sound", const_cast<char**>(kwlist), &filename))
95                 {
96                         Py_DECREF(self);
97                         return nullptr;
98                 }
99
100                 try
101                 {
102                         self->sound = new std::shared_ptr<ISound>(new File(filename));
103                 }
104                 catch(Exception& e)
105                 {
106                         Py_DECREF(self);
107                         PyErr_SetString(AUDError, e.what());
108                         return nullptr;
109                 }
110         }
111
112         return (PyObject *)self;
113 }
114
115 PyDoc_STRVAR(M_aud_Sound_data_doc,
116                          "data()\n\n"
117                          "Retrieves the data of the sound as numpy array.\n\n"
118                          ":return: A two dimensional numpy float array.\n"
119                          ":rtype: :class:`numpy.ndarray`\n\n"
120                          ".. note:: Best efficiency with cached sounds.");
121
122 static PyObject *
123 Sound_data(Sound* self)
124 {
125         std::shared_ptr<ISound> sound = *reinterpret_cast<std::shared_ptr<ISound>*>(self->sound);
126
127         auto stream_buffer = std::dynamic_pointer_cast<StreamBuffer>(sound);
128         if(!stream_buffer)
129                 stream_buffer = std::make_shared<StreamBuffer>(sound);
130         Specs specs = stream_buffer->getSpecs();
131         auto buffer = stream_buffer->getBuffer();
132
133         npy_intp dimensions[2];
134         dimensions[0] = buffer->getSize() / AUD_SAMPLE_SIZE(specs);
135         dimensions[1] = specs.channels;
136
137         PyArrayObject* array = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(2, dimensions, NPY_FLOAT));
138
139         sample_t* data = reinterpret_cast<sample_t*>(PyArray_DATA(array));
140
141         std::memcpy(data, buffer->getBuffer(), buffer->getSize());
142
143         Py_INCREF(array);
144
145         return reinterpret_cast<PyObject*>(array);
146 }
147
148 PyDoc_STRVAR(M_aud_Sound_write_doc,
149                          "write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n"
150                          "Writes the sound to a file.\n\n"
151                          ":arg filename: The path to write to.\n"
152                          ":type filename: string\n"
153                          ":arg rate: The sample rate to write with.\n"
154                          ":type rate: int\n"
155                          ":arg channels: The number of channels to write with.\n"
156                          ":type channels: int\n"
157                          ":arg format: The sample format to write with.\n"
158                          ":type format: int\n"
159                          ":arg container: The container format for the file.\n"
160                          ":type container: int\n"
161                          ":arg codec: The codec to use in the file.\n"
162                          ":type codec: int\n"
163                          ":arg bitrate: The bitrate to write with.\n"
164                          ":type bitrate: int\n"
165                          ":arg buffersize: The size of the writing buffer.\n"
166                          ":type buffersize: int\n");
167
168 static PyObject *
169 Sound_write(Sound* self, PyObject* args, PyObject* kwds)
170 {
171         const char* filename = nullptr;
172         int rate = RATE_INVALID;
173         Channels channels = CHANNELS_INVALID;
174         SampleFormat format = FORMAT_INVALID;
175         Container container = CONTAINER_INVALID;
176         Codec codec = CODEC_INVALID;
177         int bitrate = 0;
178         int buffersize = 0;
179
180         static const char* kwlist[] = {"filename", "rate", "channels", "format", "container", "codec", "bitrate", "buffersize", nullptr};
181
182         if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|iiiiiii:write", const_cast<char**>(kwlist), &filename, &rate, &channels, &format, &container, &codec, &bitrate, &buffersize))
183                 return nullptr;
184
185         try
186         {
187                 std::shared_ptr<IReader> reader = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader();
188
189                 DeviceSpecs specs;
190                 specs.specs = reader->getSpecs();
191
192                 if((rate != RATE_INVALID) && (specs.rate != rate))
193                 {
194                         specs.rate = rate;
195                         reader = std::make_shared<JOSResampleReader>(reader, rate);
196                 }
197
198                 if((channels != CHANNELS_INVALID) && (specs.channels != channels))
199                 {
200                         specs.channels = channels;
201                         reader = std::make_shared<ChannelMapperReader>(reader, channels);
202                 }
203
204                 if(format == FORMAT_INVALID)
205                         format = FORMAT_S16;
206                 specs.format = format;
207
208                 const char* invalid_container_error = "Container could not be determined from filename.";
209
210                 if(container == CONTAINER_INVALID)
211                 {
212                         std::string path = filename;
213
214                         if(path.length() < 4)
215                         {
216                                 PyErr_SetString(AUDError, invalid_container_error);
217                                 return nullptr;
218                         }
219
220                         std::string extension = path.substr(path.length() - 4);
221
222                         if(extension == ".ac3")
223                                 container = CONTAINER_AC3;
224                         else if(extension == "flac")
225                                 container = CONTAINER_FLAC;
226                         else if(extension == ".mkv")
227                                 container = CONTAINER_MATROSKA;
228                         else if(extension == ".mp2")
229                                 container = CONTAINER_MP2;
230                         else if(extension == ".mp3")
231                                 container = CONTAINER_MP3;
232                         else if(extension == ".ogg")
233                                 container = CONTAINER_OGG;
234                         else if(extension == ".wav")
235                                 container = CONTAINER_WAV;
236                         else
237                         {
238                                 PyErr_SetString(AUDError, invalid_container_error);
239                                 return nullptr;
240                         }
241                 }
242
243                 if(codec == CODEC_INVALID)
244                 {
245                         switch(container)
246                         {
247                         case CONTAINER_AC3:
248                                 codec = CODEC_AC3;
249                                 break;
250                         case CONTAINER_FLAC:
251                                 codec = CODEC_FLAC;
252                                 break;
253                         case CONTAINER_MATROSKA:
254                                 codec = CODEC_OPUS;
255                                 break;
256                         case CONTAINER_MP2:
257                                 codec = CODEC_MP2;
258                                 break;
259                         case CONTAINER_MP3:
260                                 codec = CODEC_MP3;
261                                 break;
262                         case CONTAINER_OGG:
263                                 codec = CODEC_VORBIS;
264                                 break;
265                         case CONTAINER_WAV:
266                                 codec = CODEC_PCM;
267                                 break;
268                         default:
269                                 PyErr_SetString(AUDError, "Unknown container, cannot select default codec.");
270                                 return nullptr;
271                         }
272                 }
273
274                 if(buffersize <= 0)
275                         buffersize = AUD_DEFAULT_BUFFER_SIZE;
276
277                 std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, specs, container, codec, bitrate);
278                 FileWriter::writeReader(reader, writer, 0, buffersize);
279         }
280         catch(Exception& e)
281         {
282                 PyErr_SetString(AUDError, e.what());
283                 return nullptr;
284         }
285
286         Py_RETURN_NONE;
287 }
288
289 PyDoc_STRVAR(M_aud_Sound_buffer_doc,
290                          "buffer(data, rate)\n\n"
291                          "Creates a sound from a data buffer.\n\n"
292                          ":arg data: The data as two dimensional numpy array.\n"
293                          ":type data: numpy.ndarray\n"
294                          ":arg rate: The sample rate.\n"
295                          ":type rate: double\n"
296                          ":return: The created :class:`Sound` object.\n"
297                          ":rtype: :class:`Sound`");
298
299 static PyObject *
300 Sound_buffer(PyTypeObject* type, PyObject* args)
301 {
302         PyArrayObject* array = nullptr;
303         double rate = RATE_INVALID;
304
305         if(!PyArg_ParseTuple(args, "Od:buffer", &array, &rate))
306                 return nullptr;
307
308         if((!PyObject_TypeCheck(reinterpret_cast<PyObject*>(array), &PyArray_Type)) || (PyArray_TYPE(array) != NPY_FLOAT))
309         {
310                 PyErr_SetString(PyExc_TypeError, "The data needs to be supplied as float32 numpy array!");
311                 return nullptr;
312         }
313
314         if(PyArray_NDIM(array) > 2)
315         {
316                 PyErr_SetString(PyExc_TypeError, "The array needs to have one or two dimensions!");
317                 return nullptr;
318         }
319
320         if(rate <= 0)
321         {
322                 PyErr_SetString(PyExc_TypeError, "The sample rate has to be positive!");
323                 return nullptr;
324         }
325
326         Specs specs;
327         specs.rate = rate;
328         specs.channels = CHANNELS_MONO;
329
330         if(PyArray_NDIM(array) == 2)
331                 specs.channels = static_cast<Channels>(PyArray_DIM(array, 1));
332
333         int size = PyArray_DIM(array, 0) * AUD_SAMPLE_SIZE(specs);
334
335         std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>(size);
336
337         std::memcpy(buffer->getBuffer(), PyArray_DATA(array), size);
338
339         Sound* self;
340
341         self = (Sound*)type->tp_alloc(type, 0);
342         if(self != nullptr)
343         {
344                 try
345                 {
346                         self->sound = new std::shared_ptr<StreamBuffer>(new StreamBuffer(buffer, specs));
347                 }
348                 catch(Exception& e)
349                 {
350                         Py_DECREF(self);
351                         PyErr_SetString(AUDError, e.what());
352                         return nullptr;
353                 }
354         }
355
356         return (PyObject *)self;
357 }
358
359 PyDoc_STRVAR(M_aud_Sound_cache_doc,
360                          "cache()\n\n"
361                          "Caches a sound into RAM.\n"
362                          "This saves CPU usage needed for decoding and file access if the "
363                          "underlying sound reads from a file on the harddisk, but it "
364                          "consumes a lot of memory.\n\n"
365                          ":return: The created :class:`Sound` object.\n"
366                          ":rtype: :class:`Sound`\n\n"
367                          ".. note:: Only known-length factories can be buffered.\n\n"
368                          ".. warning:: Raw PCM data needs a lot of space, only buffer "
369                          "short factories.");
370
371 static PyObject *
372 Sound_cache(Sound* self)
373 {
374         PyTypeObject* type = Py_TYPE(self);
375         Sound* parent = (Sound*)type->tp_alloc(type, 0);
376
377         if(parent != nullptr)
378         {
379                 try
380                 {
381                         parent->sound = new std::shared_ptr<ISound>(new StreamBuffer(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
382                 }
383                 catch(Exception& e)
384                 {
385                         Py_DECREF(parent);
386                         PyErr_SetString(AUDError, e.what());
387                         return nullptr;
388                 }
389         }
390
391         return (PyObject *)parent;
392 }
393
394 PyDoc_STRVAR(M_aud_Sound_file_doc,
395                          "file(filename)\n\n"
396                          "Creates a sound object of a sound file.\n\n"
397                          ":arg filename: Path of the file.\n"
398                          ":type filename: string\n"
399                          ":return: The created :class:`Sound` object.\n"
400                          ":rtype: :class:`Sound`\n\n"
401                          ".. warning:: If the file doesn't exist or can't be read you will "
402                          "not get an exception immediately, but when you try to start "
403                          "playback of that sound.");
404
405 static PyObject *
406 Sound_file(PyTypeObject* type, PyObject* args)
407 {
408         const char* filename = nullptr;
409
410         if(!PyArg_ParseTuple(args, "s:file", &filename))
411                 return nullptr;
412
413         Sound* self;
414
415         self = (Sound*)type->tp_alloc(type, 0);
416         if(self != nullptr)
417         {
418                 try
419                 {
420                         self->sound = new std::shared_ptr<ISound>(new File(filename));
421                 }
422                 catch(Exception& e)
423                 {
424                         Py_DECREF(self);
425                         PyErr_SetString(AUDError, e.what());
426                         return nullptr;
427                 }
428         }
429
430         return (PyObject *)self;
431 }
432
433 PyDoc_STRVAR(M_aud_Sound_sawtooth_doc,
434                          "sawtooth(frequency, rate=48000)\n\n"
435                          "Creates a sawtooth sound which plays a sawtooth wave.\n\n"
436                          ":arg frequency: The frequency of the sawtooth wave in Hz.\n"
437                          ":type frequency: float\n"
438                          ":arg rate: The sampling rate in Hz. It's recommended to set this "
439                          "value to the playback device's samling rate to avoid resamping.\n"
440                          ":type rate: int\n"
441                          ":return: The created :class:`Sound` object.\n"
442                          ":rtype: :class:`Sound`");
443
444 static PyObject *
445 Sound_sawtooth(PyTypeObject* type, PyObject* args)
446 {
447         float frequency;
448         double rate = 48000;
449
450         if(!PyArg_ParseTuple(args, "f|d:sawtooth", &frequency, &rate))
451                 return nullptr;
452
453         Sound* self;
454
455         self = (Sound*)type->tp_alloc(type, 0);
456         if(self != nullptr)
457         {
458                 try
459                 {
460                         self->sound = new std::shared_ptr<ISound>(new Sawtooth(frequency, (SampleRate)rate));
461                 }
462                 catch(Exception& e)
463                 {
464                         Py_DECREF(self);
465                         PyErr_SetString(AUDError, e.what());
466                         return nullptr;
467                 }
468         }
469
470         return (PyObject *)self;
471 }
472
473 PyDoc_STRVAR(M_aud_Sound_silence_doc,
474                          "silence()\n\n"
475                          "Creates a silence sound which plays simple silence.\n\n"
476                          ":return: The created :class:`Sound` object.\n"
477                          ":rtype: :class:`Sound`");
478
479 static PyObject *
480 Sound_silence(PyTypeObject* type)
481 {
482         Sound* self;
483
484         self = (Sound*)type->tp_alloc(type, 0);
485         if(self != nullptr)
486         {
487                 try
488                 {
489                         self->sound = new std::shared_ptr<ISound>(new Silence());
490                 }
491                 catch(Exception& e)
492                 {
493                         Py_DECREF(self);
494                         PyErr_SetString(AUDError, e.what());
495                         return nullptr;
496                 }
497         }
498
499         return (PyObject *)self;
500 }
501
502 PyDoc_STRVAR(M_aud_Sound_sine_doc,
503                          "sine(frequency, rate=48000)\n\n"
504                          "Creates a sine sound which plays a sine wave.\n\n"
505                          ":arg frequency: The frequency of the sine wave in Hz.\n"
506                          ":type frequency: float\n"
507                          ":arg rate: The sampling rate in Hz. It's recommended to set this "
508                          "value to the playback device's samling rate to avoid resamping.\n"
509                          ":type rate: int\n"
510                          ":return: The created :class:`Sound` object.\n"
511                          ":rtype: :class:`Sound`");
512
513 static PyObject *
514 Sound_sine(PyTypeObject* type, PyObject* args)
515 {
516         float frequency;
517         double rate = 48000;
518
519         if(!PyArg_ParseTuple(args, "f|d:sine", &frequency, &rate))
520                 return nullptr;
521
522         Sound* self;
523
524         self = (Sound*)type->tp_alloc(type, 0);
525         if(self != nullptr)
526         {
527                 try
528                 {
529                         self->sound = new std::shared_ptr<ISound>(new Sine(frequency, (SampleRate)rate));
530                 }
531                 catch(Exception& e)
532                 {
533                         Py_DECREF(self);
534                         PyErr_SetString(AUDError, e.what());
535                         return nullptr;
536                 }
537         }
538
539         return (PyObject *)self;
540 }
541
542 PyDoc_STRVAR(M_aud_Sound_square_doc,
543                          "square(frequency, rate=48000)\n\n"
544                          "Creates a square sound which plays a square wave.\n\n"
545                          ":arg frequency: The frequency of the square wave in Hz.\n"
546                          ":type frequency: float\n"
547                          ":arg rate: The sampling rate in Hz. It's recommended to set this "
548                          "value to the playback device's samling rate to avoid resamping.\n"
549                          ":type rate: int\n"
550                          ":return: The created :class:`Sound` object.\n"
551                          ":rtype: :class:`Sound`");
552
553 static PyObject *
554 Sound_square(PyTypeObject* type, PyObject* args)
555 {
556         float frequency;
557         double rate = 48000;
558
559         if(!PyArg_ParseTuple(args, "f|d:square", &frequency, &rate))
560                 return nullptr;
561
562         Sound* self;
563
564         self = (Sound*)type->tp_alloc(type, 0);
565         if(self != nullptr)
566         {
567                 try
568                 {
569                         self->sound = new std::shared_ptr<ISound>(new Square(frequency, (SampleRate)rate));
570                 }
571                 catch(Exception& e)
572                 {
573                         Py_DECREF(self);
574                         PyErr_SetString(AUDError, e.what());
575                         return nullptr;
576                 }
577         }
578
579         return (PyObject *)self;
580 }
581
582 PyDoc_STRVAR(M_aud_Sound_triangle_doc,
583                          "triangle(frequency, rate=48000)\n\n"
584                          "Creates a triangle sound which plays a triangle wave.\n\n"
585                          ":arg frequency: The frequency of the triangle wave in Hz.\n"
586                          ":type frequency: float\n"
587                          ":arg rate: The sampling rate in Hz. It's recommended to set this "
588                          "value to the playback device's samling rate to avoid resamping.\n"
589                          ":type rate: int\n"
590                          ":return: The created :class:`Sound` object.\n"
591                          ":rtype: :class:`Sound`");
592
593 static PyObject *
594 Sound_triangle(PyTypeObject* type, PyObject* args)
595 {
596         float frequency;
597         double rate = 48000;
598
599         if(!PyArg_ParseTuple(args, "f|d:triangle", &frequency, &rate))
600                 return nullptr;
601
602         Sound* self;
603
604         self = (Sound*)type->tp_alloc(type, 0);
605         if(self != nullptr)
606         {
607                 try
608                 {
609                         self->sound = new std::shared_ptr<ISound>(new Triangle(frequency, (SampleRate)rate));
610                 }
611                 catch(Exception& e)
612                 {
613                         Py_DECREF(self);
614                         PyErr_SetString(AUDError, e.what());
615                         return nullptr;
616                 }
617         }
618
619         return (PyObject *)self;
620 }
621
622 PyDoc_STRVAR(M_aud_Sound_accumulate_doc,
623                          "accumulate(additive=False)\n\n"
624                          "Accumulates a sound by summing over positive input differences thus generating a monotonic sigal. "
625                          "If additivity is set to true negative input differences get added too, but positive ones with a factor of two. "
626                          "Note that with additivity the signal is not monotonic anymore.\n\n"
627                          ":arg additive: Whether the accumulation should be additive or not.\n"
628                          ":type time: bool\n"
629                          ":return: The created :class:`Sound` object.\n"
630                          ":rtype: :class:`Sound`");
631
632 static PyObject *
633 Sound_accumulate(Sound* self, PyObject* args)
634 {
635         bool additive = false;
636         PyObject* additiveo;
637
638         if(!PyArg_ParseTuple(args, "|O:accumulate", &additiveo))
639                 return nullptr;
640
641         PyTypeObject* type = Py_TYPE(self);
642         Sound* parent = (Sound*)type->tp_alloc(type, 0);
643
644         if(parent != nullptr)
645         {
646                 if(additiveo != nullptr)
647                 {
648                         if(!PyBool_Check(additiveo))
649                         {
650                                 PyErr_SetString(PyExc_TypeError, "additive is not a boolean!");
651                                 return nullptr;
652                         }
653
654                         additive = additiveo == Py_True;
655                 }
656
657                 try
658                 {
659                         parent->sound = new std::shared_ptr<ISound>(new Accumulator(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), additive));
660                 }
661                 catch(Exception& e)
662                 {
663                         Py_DECREF(parent);
664                         PyErr_SetString(AUDError, e.what());
665                         return nullptr;
666                 }
667         }
668
669         return (PyObject *)parent;
670 }
671
672 PyDoc_STRVAR(M_aud_Sound_ADSR_doc,
673                          "ADSR(attack,decay,sustain,release)\n\n"
674                          "Attack-Decay-Sustain-Release envelopes the volume of a sound. "
675                          "Note: there is currently no way to trigger the release with this API.\n\n"
676                          ":arg attack: The attack time in seconds.\n"
677                          ":type attack: float\n"
678                          ":arg decay: The decay time in seconds.\n"
679                          ":type decay: float\n"
680                          ":arg sustain: The sustain level.\n"
681                          ":type sustain: float\n"
682                          ":arg release: The release level.\n"
683                          ":type release: float\n"
684                          ":return: The created :class:`Sound` object.\n"
685                          ":rtype: :class:`Sound`");
686
687 static PyObject *
688 Sound_ADSR(Sound* self, PyObject* args)
689 {
690         float attack, decay, sustain, release;
691
692         if(!PyArg_ParseTuple(args, "ffff:ADSR", &attack, &decay, &sustain, &release))
693                 return nullptr;
694
695         PyTypeObject* type = Py_TYPE(self);
696         Sound* parent = (Sound*)type->tp_alloc(type, 0);
697
698         if(parent != nullptr)
699         {
700                 try
701                 {
702                         parent->sound = new std::shared_ptr<ISound>(new ADSR(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), attack, decay, sustain, release));
703                 }
704                 catch(Exception& e)
705                 {
706                         Py_DECREF(parent);
707                         PyErr_SetString(AUDError, e.what());
708                         return nullptr;
709                 }
710         }
711
712         return (PyObject *)parent;
713 }
714
715 PyDoc_STRVAR(M_aud_Sound_delay_doc,
716                          "delay(time)\n\n"
717                          "Delays by playing adding silence in front of the other sound's "
718                          "data.\n\n"
719                          ":arg time: How many seconds of silence should be added before "
720                          "the sound.\n"
721                          ":type time: float\n"
722                          ":return: The created :class:`Sound` object.\n"
723                          ":rtype: :class:`Sound`");
724
725 static PyObject *
726 Sound_delay(Sound* self, PyObject* args)
727 {
728         float delay;
729
730         if(!PyArg_ParseTuple(args, "f:delay", &delay))
731                 return nullptr;
732
733         PyTypeObject* type = Py_TYPE(self);
734         Sound* parent = (Sound*)type->tp_alloc(type, 0);
735
736         if(parent != nullptr)
737         {
738                 try
739                 {
740                         parent->sound = new std::shared_ptr<ISound>(new Delay(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), delay));
741                 }
742                 catch(Exception& e)
743                 {
744                         Py_DECREF(parent);
745                         PyErr_SetString(AUDError, e.what());
746                         return nullptr;
747                 }
748         }
749
750         return (PyObject *)parent;
751 }
752
753 PyDoc_STRVAR(M_aud_Sound_envelope_doc,
754                          "envelope(attack, release, threshold, arthreshold)\n\n"
755                          "Delays by playing adding silence in front of the other sound's "
756                          "data.\n\n"
757                          ":arg attack: The attack factor.\n"
758                          ":type attack: float\n"
759                          ":arg release: The release factor.\n"
760                          ":type release: float\n"
761                          ":arg threshold: The general threshold value.\n"
762                          ":type threshold: float\n"
763                          ":arg arthreshold: The attack/release threshold value.\n"
764                          ":type arthreshold: float\n"
765                          ":return: The created :class:`Sound` object.\n"
766                          ":rtype: :class:`Sound`");
767
768 static PyObject *
769 Sound_envelope(Sound* self, PyObject* args)
770 {
771         float attack, release, threshold, arthreshold;
772
773         if(!PyArg_ParseTuple(args, "ffff:envelope", &attack, &release, &threshold, &arthreshold))
774                 return nullptr;
775
776         PyTypeObject* type = Py_TYPE(self);
777         Sound* parent = (Sound*)type->tp_alloc(type, 0);
778
779         if(parent != nullptr)
780         {
781                 try
782                 {
783                         parent->sound = new std::shared_ptr<ISound>(new Envelope(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), attack, release, threshold, arthreshold));
784                 }
785                 catch(Exception& e)
786                 {
787                         Py_DECREF(parent);
788                         PyErr_SetString(AUDError, e.what());
789                         return nullptr;
790                 }
791         }
792
793         return (PyObject *)parent;
794 }
795
796 PyDoc_STRVAR(M_aud_Sound_fadein_doc,
797                          "fadein(start, length)\n\n"
798                          "Fades a sound in by raising the volume linearly in the given "
799                          "time interval.\n\n"
800                          ":arg start: Time in seconds when the fading should start.\n"
801                          ":type start: float\n"
802                          ":arg length: Time in seconds how long the fading should last.\n"
803                          ":type length: float\n"
804                          ":return: The created :class:`Sound` object.\n"
805                          ":rtype: :class:`Sound`\n\n"
806                          ".. note:: Before the fade starts it plays silence.");
807
808 static PyObject *
809 Sound_fadein(Sound* self, PyObject* args)
810 {
811         float start, length;
812
813         if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
814                 return nullptr;
815
816         PyTypeObject* type = Py_TYPE(self);
817         Sound* parent = (Sound*)type->tp_alloc(type, 0);
818
819         if(parent != nullptr)
820         {
821                 try
822                 {
823                         parent->sound = new std::shared_ptr<ISound>(new Fader(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), FADE_IN, start, length));
824                 }
825                 catch(Exception& e)
826                 {
827                         Py_DECREF(parent);
828                         PyErr_SetString(AUDError, e.what());
829                         return nullptr;
830                 }
831         }
832
833         return (PyObject *)parent;
834 }
835
836 PyDoc_STRVAR(M_aud_Sound_fadeout_doc,
837                          "fadeout(start, length)\n\n"
838                          "Fades a sound in by lowering the volume linearly in the given "
839                          "time interval.\n\n"
840                          ":arg start: Time in seconds when the fading should start.\n"
841                          ":type start: float\n"
842                          ":arg length: Time in seconds how long the fading should last.\n"
843                          ":type length: float\n"
844                          ":return: The created :class:`Sound` object.\n"
845                          ":rtype: :class:`Sound`\n\n"
846                          ".. note:: After the fade this sound plays silence, so that "
847                          "the length of the sound is not altered.");
848
849 static PyObject *
850 Sound_fadeout(Sound* self, PyObject* args)
851 {
852         float start, length;
853
854         if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
855                 return nullptr;
856
857         PyTypeObject* type = Py_TYPE(self);
858         Sound* parent = (Sound*)type->tp_alloc(type, 0);
859
860         if(parent != nullptr)
861         {
862                 try
863                 {
864                         parent->sound = new std::shared_ptr<ISound>(new Fader(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), FADE_OUT, start, length));
865                 }
866                 catch(Exception& e)
867                 {
868                         Py_DECREF(parent);
869                         PyErr_SetString(AUDError, e.what());
870                         return nullptr;
871                 }
872         }
873
874         return (PyObject *)parent;
875 }
876
877 PyDoc_STRVAR(M_aud_Sound_filter_doc,
878                          "filter(b, a = (1))\n\n"
879                          "Filters a sound with the supplied IIR filter coefficients.\n"
880                          "Without the second parameter you'll get a FIR filter.\n"
881                          "If the first value of the a sequence is 0 it will be set to 1 "
882                          "automatically.\n"
883                          "If the first value of the a sequence is neither 0 nor 1, all "
884                          "filter coefficients will be scaled by this value so that it is 1 "
885                          "in the end, you don't have to scale yourself.\n\n"
886                          ":arg b: The nominator filter coefficients.\n"
887                          ":type b: sequence of float\n"
888                          ":arg a: The denominator filter coefficients.\n"
889                          ":type a: sequence of float\n"
890                          ":return: The created :class:`Sound` object.\n"
891                          ":rtype: :class:`Sound`");
892
893 static PyObject *
894 Sound_filter(Sound* self, PyObject* args)
895 {
896         PyObject* py_b;
897         PyObject* py_a = nullptr;
898         Py_ssize_t py_a_len;
899         Py_ssize_t py_b_len;
900
901         if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
902                 return nullptr;
903
904         if(!PySequence_Check(py_b) || (py_a != nullptr && !PySequence_Check(py_a)))
905         {
906                 PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
907                 return nullptr;
908         }
909
910         py_a_len= py_a ? PySequence_Size(py_a) : 0;
911         py_b_len= PySequence_Size(py_b);
912
913         if(!py_b_len || ((py_a != nullptr) && !py_a_len))
914         {
915                 PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
916                 return nullptr;
917         }
918
919         std::vector<float> a, b;
920         PyObject* py_value;
921         float value;
922
923         for(Py_ssize_t i = 0; i < py_b_len; i++)
924         {
925                 py_value = PySequence_GetItem(py_b, i);
926                 value= (float)PyFloat_AsDouble(py_value);
927                 Py_DECREF(py_value);
928
929                 if(value == -1.0f && PyErr_Occurred()) {
930                         return nullptr;
931                 }
932
933                 b.push_back(value);
934         }
935
936         if(py_a)
937         {
938                 for(Py_ssize_t i = 0; i < py_a_len; i++)
939                 {
940                         py_value = PySequence_GetItem(py_a, i);
941                         value= (float)PyFloat_AsDouble(py_value);
942                         Py_DECREF(py_value);
943
944                         if(value == -1.0f && PyErr_Occurred()) {
945                                 return nullptr;
946                         }
947
948                         a.push_back(value);
949                 }
950
951                 if(a[0] == 0)
952                         a[0] = 1;
953         }
954         else
955                 a.push_back(1);
956
957         PyTypeObject* type = Py_TYPE(self);
958         Sound* parent = (Sound*)type->tp_alloc(type, 0);
959
960         if(parent != nullptr)
961         {
962                 try
963                 {
964                         parent->sound = new std::shared_ptr<ISound>(new IIRFilter(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), b, a));
965                 }
966                 catch(Exception& e)
967                 {
968                         Py_DECREF(parent);
969                         PyErr_SetString(AUDError, e.what());
970                         return nullptr;
971                 }
972         }
973
974         return (PyObject *)parent;
975 }
976
977 PyDoc_STRVAR(M_aud_Sound_highpass_doc,
978                          "highpass(frequency, Q=0.5)\n\n"
979                          "Creates a second order highpass filter based on the transfer "
980                          "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
981                          ":arg frequency: The cut off trequency of the highpass.\n"
982                          ":type frequency: float\n"
983                          ":arg Q: Q factor of the lowpass.\n"
984                          ":type Q: float\n"
985                          ":return: The created :class:`Sound` object.\n"
986                          ":rtype: :class:`Sound`");
987
988 static PyObject *
989 Sound_highpass(Sound* self, PyObject* args)
990 {
991         float frequency;
992         float Q = 0.5;
993
994         if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
995                 return nullptr;
996
997         PyTypeObject* type = Py_TYPE(self);
998         Sound* parent = (Sound*)type->tp_alloc(type, 0);
999
1000         if(parent != nullptr)
1001         {
1002                 try
1003                 {
1004                         parent->sound = new std::shared_ptr<ISound>(new Highpass(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), frequency, Q));
1005                 }
1006                 catch(Exception& e)
1007                 {
1008                         Py_DECREF(parent);
1009                         PyErr_SetString(AUDError, e.what());
1010                         return nullptr;
1011                 }
1012         }
1013
1014         return (PyObject *)parent;
1015 }
1016
1017 PyDoc_STRVAR(M_aud_Sound_limit_doc,
1018                          "limit(start, end)\n\n"
1019                          "Limits a sound within a specific start and end time.\n\n"
1020                          ":arg start: Start time in seconds.\n"
1021                          ":type start: float\n"
1022                          ":arg end: End time in seconds.\n"
1023                          ":type end: float\n"
1024                          ":return: The created :class:`Sound` object.\n"
1025                          ":rtype: :class:`Sound`");
1026
1027 static PyObject *
1028 Sound_limit(Sound* self, PyObject* args)
1029 {
1030         float start, end;
1031
1032         if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
1033                 return nullptr;
1034
1035         PyTypeObject* type = Py_TYPE(self);
1036         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1037
1038         if(parent != nullptr)
1039         {
1040                 try
1041                 {
1042                         parent->sound = new std::shared_ptr<ISound>(new Limiter(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), start, end));
1043                 }
1044                 catch(Exception& e)
1045                 {
1046                         Py_DECREF(parent);
1047                         PyErr_SetString(AUDError, e.what());
1048                         return nullptr;
1049                 }
1050         }
1051
1052         return (PyObject *)parent;
1053 }
1054
1055 PyDoc_STRVAR(M_aud_Sound_loop_doc,
1056                          "loop(count)\n\n"
1057                          "Loops a sound.\n\n"
1058                          ":arg count: How often the sound should be looped. "
1059                          "Negative values mean endlessly.\n"
1060                          ":type count: integer\n"
1061                          ":return: The created :class:`Sound` object.\n"
1062                          ":rtype: :class:`Sound`\n\n"
1063                          ".. note:: This is a filter function, you might consider using "
1064                          ":attr:`Handle.loop_count` instead.");
1065
1066 static PyObject *
1067 Sound_loop(Sound* self, PyObject* args)
1068 {
1069         int loop;
1070
1071         if(!PyArg_ParseTuple(args, "i:loop", &loop))
1072                 return nullptr;
1073
1074         PyTypeObject* type = Py_TYPE(self);
1075         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1076
1077         if(parent != nullptr)
1078         {
1079                 try
1080                 {
1081                         parent->sound = new std::shared_ptr<ISound>(new Loop(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), loop));
1082                 }
1083                 catch(Exception& e)
1084                 {
1085                         Py_DECREF(parent);
1086                         PyErr_SetString(AUDError, e.what());
1087                         return nullptr;
1088                 }
1089         }
1090
1091         return (PyObject *)parent;
1092 }
1093
1094 PyDoc_STRVAR(M_aud_Sound_lowpass_doc,
1095                          "lowpass(frequency, Q=0.5)\n\n"
1096                          "Creates a second order lowpass filter based on the transfer "
1097                          "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
1098                          ":arg frequency: The cut off trequency of the lowpass.\n"
1099                          ":type frequency: float\n"
1100                          ":arg Q: Q factor of the lowpass.\n"
1101                          ":type Q: float\n"
1102                          ":return: The created :class:`Sound` object.\n"
1103                          ":rtype: :class:`Sound`");
1104
1105 static PyObject *
1106 Sound_lowpass(Sound* self, PyObject* args)
1107 {
1108         float frequency;
1109         float Q = 0.5;
1110
1111         if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
1112                 return nullptr;
1113
1114         PyTypeObject* type = Py_TYPE(self);
1115         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1116
1117         if(parent != nullptr)
1118         {
1119                 try
1120                 {
1121                         parent->sound = new std::shared_ptr<ISound>(new Lowpass(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), frequency, Q));
1122                 }
1123                 catch(Exception& e)
1124                 {
1125                         Py_DECREF(parent);
1126                         PyErr_SetString(AUDError, e.what());
1127                         return nullptr;
1128                 }
1129         }
1130
1131         return (PyObject *)parent;
1132 }
1133
1134 PyDoc_STRVAR(M_aud_Sound_pitch_doc,
1135                          "pitch(factor)\n\n"
1136                          "Changes the pitch of a sound with a specific factor.\n\n"
1137                          ":arg factor: The factor to change the pitch with.\n"
1138                          ":type factor: float\n"
1139                          ":return: The created :class:`Sound` object.\n"
1140                          ":rtype: :class:`Sound`\n\n"
1141                          ".. note:: This is done by changing the sample rate of the "
1142                          "underlying sound, which has to be an integer, so the factor "
1143                          "value rounded and the factor may not be 100 % accurate.\n\n"
1144                          ".. note:: This is a filter function, you might consider using "
1145                          ":attr:`Handle.pitch` instead.");
1146
1147 static PyObject *
1148 Sound_pitch(Sound* self, PyObject* args)
1149 {
1150         float factor;
1151
1152         if(!PyArg_ParseTuple(args, "f:pitch", &factor))
1153                 return nullptr;
1154
1155         PyTypeObject* type = Py_TYPE(self);
1156         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1157
1158         if(parent != nullptr)
1159         {
1160                 try
1161                 {
1162                         parent->sound = new std::shared_ptr<ISound>(new Pitch(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), factor));
1163                 }
1164                 catch(Exception& e)
1165                 {
1166                         Py_DECREF(parent);
1167                         PyErr_SetString(AUDError, e.what());
1168                         return nullptr;
1169                 }
1170         }
1171
1172         return (PyObject *)parent;
1173 }
1174
1175 PyDoc_STRVAR(M_aud_Sound_rechannel_doc,
1176                          "rechannel(channels)\n\n"
1177                          "Rechannels the sound.\n\n"
1178                          ":arg channels: The new channel configuration.\n"
1179                          ":type channels: int\n"
1180                          ":return: The created :class:`Sound` object.\n"
1181                          ":rtype: :class:`Sound`");
1182
1183 static PyObject *
1184 Sound_rechannel(Sound* self, PyObject* args)
1185 {
1186         int channels;
1187
1188         if(!PyArg_ParseTuple(args, "i:rechannel", &channels))
1189                 return nullptr;
1190
1191         PyTypeObject* type = Py_TYPE(self);
1192         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1193
1194         if(parent != nullptr)
1195         {
1196                 try
1197                 {
1198                         DeviceSpecs specs;
1199                         specs.channels = static_cast<Channels>(channels);
1200                         specs.rate = RATE_INVALID;
1201                         specs.format = FORMAT_INVALID;
1202                         parent->sound = new std::shared_ptr<ISound>(new ChannelMapper(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
1203                 }
1204                 catch(Exception& e)
1205                 {
1206                         Py_DECREF(parent);
1207                         PyErr_SetString(AUDError, e.what());
1208                         return nullptr;
1209                 }
1210         }
1211
1212         return (PyObject *)parent;
1213 }
1214
1215 PyDoc_STRVAR(M_aud_Sound_resample_doc,
1216                          "resample(rate, high_quality)\n\n"
1217                          "Resamples the sound.\n\n"
1218                          ":arg rate: The new sample rate.\n"
1219                          ":type rate: double\n"
1220                          ":arg high_quality: When true use a higher quality but slower resampler.\n"
1221                          ":type high_quality: bool\n"
1222                          ":return: The created :class:`Sound` object.\n"
1223                          ":rtype: :class:`Sound`");
1224
1225 static PyObject *
1226 Sound_resample(Sound* self, PyObject* args)
1227 {
1228         double rate;
1229         PyObject* high_qualityo;
1230         bool high_quality = false;
1231
1232         if(!PyArg_ParseTuple(args, "d|O:resample", &rate, &high_qualityo))
1233                 return nullptr;
1234
1235         if(!PyBool_Check(high_qualityo))
1236         {
1237                 PyErr_SetString(PyExc_TypeError, "high_quality is not a boolean!");
1238                 return nullptr;
1239         }
1240
1241         high_quality = high_qualityo == Py_True;
1242
1243         PyTypeObject* type = Py_TYPE(self);
1244         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1245
1246         if(parent != nullptr)
1247         {
1248                 try
1249                 {
1250                         DeviceSpecs specs;
1251                         specs.channels = CHANNELS_INVALID;
1252                         specs.rate = rate;
1253                         specs.format = FORMAT_INVALID;
1254                         if(high_quality)
1255                                 parent->sound = new std::shared_ptr<ISound>(new JOSResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
1256                         else
1257                                 parent->sound = new std::shared_ptr<ISound>(new LinearResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
1258                 }
1259                 catch(Exception& e)
1260                 {
1261                         Py_DECREF(parent);
1262                         PyErr_SetString(AUDError, e.what());
1263                         return nullptr;
1264                 }
1265         }
1266
1267         return (PyObject *)parent;
1268 }
1269
1270 PyDoc_STRVAR(M_aud_Sound_reverse_doc,
1271                          "reverse()\n\n"
1272                          "Plays a sound reversed.\n\n"
1273                          ":return: The created :class:`Sound` object.\n"
1274                          ":rtype: :class:`Sound`\n\n"
1275                          ".. note:: The sound has to have a finite length and has to be "
1276                          "seekable. It's recommended to use this only with factories     with "
1277                          "fast and accurate seeking, which is not true for encoded audio "
1278                          "files, such ones should be buffered using :meth:`cache` before "
1279                          "being played reversed.\n\n"
1280                          ".. warning:: If seeking is not accurate in the underlying sound "
1281                          "you'll likely hear skips/jumps/cracks.");
1282
1283 static PyObject *
1284 Sound_reverse(Sound* self)
1285 {
1286         PyTypeObject* type = Py_TYPE(self);
1287         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1288
1289         if(parent != nullptr)
1290         {
1291                 try
1292                 {
1293                         parent->sound = new std::shared_ptr<ISound>(new Reverse(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
1294                 }
1295                 catch(Exception& e)
1296                 {
1297                         Py_DECREF(parent);
1298                         PyErr_SetString(AUDError, e.what());
1299                         return nullptr;
1300                 }
1301         }
1302
1303         return (PyObject *)parent;
1304 }
1305
1306 PyDoc_STRVAR(M_aud_Sound_sum_doc,
1307                          "sum()\n\n"
1308                          "Sums the samples of a sound.\n\n"
1309                          ":return: The created :class:`Sound` object.\n"
1310                          ":rtype: :class:`Sound`");
1311
1312 static PyObject *
1313 Sound_sum(Sound* self)
1314 {
1315         PyTypeObject* type = Py_TYPE(self);
1316         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1317
1318         if(parent != nullptr)
1319         {
1320                 try
1321                 {
1322                         parent->sound = new std::shared_ptr<ISound>(new Sum(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
1323                 }
1324                 catch(Exception& e)
1325                 {
1326                         Py_DECREF(parent);
1327                         PyErr_SetString(AUDError, e.what());
1328                         return nullptr;
1329                 }
1330         }
1331
1332         return (PyObject *)parent;
1333 }
1334
1335 PyDoc_STRVAR(M_aud_Sound_threshold_doc,
1336                          "threshold(threshold = 0)\n\n"
1337                          "Makes a threshold wave out of an audio wave by setting all samples "
1338                          "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
1339                          "all between to 0.\n\n"
1340                          ":arg threshold: Threshold value over which an amplitude counts "
1341                          "non-zero.\n"
1342                          ":type threshold: float\n"
1343                          ":return: The created :class:`Sound` object.\n"
1344                          ":rtype: :class:`Sound`");
1345
1346 static PyObject *
1347 Sound_threshold(Sound* self, PyObject* args)
1348 {
1349         float threshold = 0;
1350
1351         if(!PyArg_ParseTuple(args, "|f:threshold", &threshold))
1352                 return nullptr;
1353
1354         PyTypeObject* type = Py_TYPE(self);
1355         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1356
1357         if(parent != nullptr)
1358         {
1359                 try
1360                 {
1361                         parent->sound = new std::shared_ptr<ISound>(new Threshold(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), threshold));
1362                 }
1363                 catch(Exception& e)
1364                 {
1365                         Py_DECREF(parent);
1366                         PyErr_SetString(AUDError, e.what());
1367                         return nullptr;
1368                 }
1369         }
1370
1371         return (PyObject *)parent;
1372 }
1373
1374 PyDoc_STRVAR(M_aud_Sound_volume_doc,
1375                          "volume(volume)\n\n"
1376                          "Changes the volume of a sound.\n\n"
1377                          ":arg volume: The new volume..\n"
1378                          ":type volume: float\n"
1379                          ":return: The created :class:`Sound` object.\n"
1380                          ":rtype: :class:`Sound`\n\n"
1381                          ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
1382                          ".. note:: This is a filter function, you might consider using "
1383                          ":attr:`Handle.volume` instead.");
1384
1385 static PyObject *
1386 Sound_volume(Sound* self, PyObject* args)
1387 {
1388         float volume;
1389
1390         if(!PyArg_ParseTuple(args, "f:volume", &volume))
1391                 return nullptr;
1392
1393         PyTypeObject* type = Py_TYPE(self);
1394         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1395
1396         if(parent != nullptr)
1397         {
1398                 try
1399                 {
1400                         parent->sound = new std::shared_ptr<ISound>(new Volume(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), volume));
1401                 }
1402                 catch(Exception& e)
1403                 {
1404                         Py_DECREF(parent);
1405                         PyErr_SetString(AUDError, e.what());
1406                         return nullptr;
1407                 }
1408         }
1409
1410         return (PyObject *)parent;
1411 }
1412
1413 PyDoc_STRVAR(M_aud_Sound_join_doc,
1414                          "join(sound)\n\n"
1415                          "Plays two factories in sequence.\n\n"
1416                          ":arg sound: The sound to play second.\n"
1417                          ":type sound: :class:`Sound`\n"
1418                          ":return: The created :class:`Sound` object.\n"
1419                          ":rtype: :class:`Sound`\n\n"
1420                          ".. note:: The two factories have to have the same specifications "
1421                          "(channels and samplerate).");
1422
1423 static PyObject *
1424 Sound_join(Sound* self, PyObject* object)
1425 {
1426         PyTypeObject* type = Py_TYPE(self);
1427
1428         if(!PyObject_TypeCheck(object, type))
1429         {
1430                 PyErr_SetString(PyExc_TypeError, "Object has to be of type Sound!");
1431                 return nullptr;
1432         }
1433
1434         Sound* parent;
1435         Sound* child = (Sound*)object;
1436
1437         parent = (Sound*)type->tp_alloc(type, 0);
1438         if(parent != nullptr)
1439         {
1440                 try
1441                 {
1442                         parent->sound = new std::shared_ptr<ISound>(new Double(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ISound>*>(child->sound)));
1443                 }
1444                 catch(Exception& e)
1445                 {
1446                         Py_DECREF(parent);
1447                         PyErr_SetString(AUDError, e.what());
1448                         return nullptr;
1449                 }
1450         }
1451
1452         return (PyObject *)parent;
1453 }
1454
1455 PyDoc_STRVAR(M_aud_Sound_mix_doc,
1456                          "mix(sound)\n\n"
1457                          "Mixes two factories.\n\n"
1458                          ":arg sound: The sound to mix over the other.\n"
1459                          ":type sound: :class:`Sound`\n"
1460                          ":return: The created :class:`Sound` object.\n"
1461                          ":rtype: :class:`Sound`\n\n"
1462                          ".. note:: The two factories have to have the same specifications "
1463                          "(channels and samplerate).");
1464
1465 static PyObject *
1466 Sound_mix(Sound* self, PyObject* object)
1467 {
1468         PyTypeObject* type = Py_TYPE(self);
1469
1470         if(!PyObject_TypeCheck(object, type))
1471         {
1472                 PyErr_SetString(PyExc_TypeError, "Object is not of type Sound!");
1473                 return nullptr;
1474         }
1475
1476         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1477         Sound* child = (Sound*)object;
1478
1479         if(parent != nullptr)
1480         {
1481                 try
1482                 {
1483                         parent->sound = new std::shared_ptr<ISound>(new Superpose(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ISound>*>(child->sound)));
1484                 }
1485                 catch(Exception& e)
1486                 {
1487                         Py_DECREF(parent);
1488                         PyErr_SetString(AUDError, e.what());
1489                         return nullptr;
1490                 }
1491         }
1492
1493         return (PyObject *)parent;
1494 }
1495
1496 PyDoc_STRVAR(M_aud_Sound_pingpong_doc,
1497                          "pingpong()\n\n"
1498                          "Plays a sound forward and then backward.\n"
1499                          "This is like joining a sound with its reverse.\n\n"
1500                          ":return: The created :class:`Sound` object.\n"
1501                          ":rtype: :class:`Sound`");
1502
1503 static PyObject *
1504 Sound_pingpong(Sound* self)
1505 {
1506         PyTypeObject* type = Py_TYPE(self);
1507         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1508
1509         if(parent != nullptr)
1510         {
1511                 try
1512                 {
1513                         parent->sound = new std::shared_ptr<ISound>(new PingPong(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
1514                 }
1515                 catch(Exception& e)
1516                 {
1517                         Py_DECREF(parent);
1518                         PyErr_SetString(AUDError, e.what());
1519                         return nullptr;
1520                 }
1521         }
1522
1523         return (PyObject *)parent;
1524 }
1525
1526 PyDoc_STRVAR(M_aud_Sound_list_doc,
1527         "list()\n\n"
1528         "Creates an empty sound list that can contain several sounds.\n\n"
1529         ":arg random: wether the playback will be random or not.\n"
1530         ":type random: int\n"
1531         ":return: The created :class:`Sound` object.\n"
1532         ":rtype: :class:`Sound`");
1533
1534 static PyObject *
1535 Sound_list(PyTypeObject* type, PyObject* args)
1536 {
1537         int random;
1538
1539         if(!PyArg_ParseTuple(args, "i:random", &random))
1540                 return nullptr;
1541
1542         Sound* self;
1543
1544         self = (Sound*)type->tp_alloc(type, 0);
1545         if(self != nullptr)
1546         {
1547                 try
1548                 {
1549                         self->sound = new std::shared_ptr<ISound>(new SoundList(random));
1550                 }
1551                 catch(Exception& e)
1552                 {
1553                         Py_DECREF(self);
1554                         PyErr_SetString(AUDError, e.what());
1555                         return nullptr;
1556                 }
1557         }
1558
1559         return (PyObject *)self;
1560 }
1561
1562 PyDoc_STRVAR(M_aud_Sound_mutable_doc,
1563         "mutable()\n\n"
1564         "Creates a sound that will be restarted when sought backwards.\n"
1565         "If the original sound is a sound list, the playing sound can change.\n\n"
1566         ":return: The created :class:`Sound` object.\n"
1567         ":rtype: :class:`Sound`");
1568
1569 static PyObject *
1570 Sound_mutable(Sound* self)
1571 {
1572         PyTypeObject* type = Py_TYPE(self);
1573         Sound* parent = (Sound*)type->tp_alloc(type, 0);
1574
1575         if(parent != nullptr)
1576         {
1577                 try
1578                 {
1579                         parent->sound = new std::shared_ptr<ISound>(new MutableSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
1580                 }
1581                 catch(Exception& e)
1582                 {
1583                         Py_DECREF(parent);
1584                         PyErr_SetString(AUDError, e.what());
1585                         return nullptr;
1586                 }
1587         }
1588
1589         return (PyObject *)parent;
1590 }
1591
1592 PyDoc_STRVAR(M_aud_Sound_list_addSound_doc,
1593         "addSound(sound)\n\n"
1594         "Adds a new sound to a sound list.\n\n"
1595         ":arg sound: The sound that will be added to the list.\n"
1596         ":type sound: :class:`Sound`\n\n"
1597         ".. note:: You can only add a sound to a sound list.");
1598         
1599 static PyObject *
1600 Sound_list_addSound(Sound* self, PyObject* object)
1601 {
1602         PyTypeObject* type = Py_TYPE(self);
1603
1604         if(!PyObject_TypeCheck(object, type))
1605         {
1606                 PyErr_SetString(PyExc_TypeError, "Object has to be of type Sound!");
1607                 return nullptr;
1608         }
1609
1610         Sound* child = (Sound*)object;
1611         try
1612         {
1613                 (*reinterpret_cast<std::shared_ptr<SoundList>*>(self->sound))->addSound(*reinterpret_cast<std::shared_ptr<ISound>*>(child->sound));
1614                 Py_RETURN_NONE;
1615         }
1616         catch(Exception& e)
1617         {
1618                 PyErr_SetString(AUDError, e.what());
1619                 return nullptr;
1620         }
1621 }
1622
1623 #ifdef WITH_CONVOLUTION
1624
1625 PyDoc_STRVAR(M_aud_Sound_convolver_doc,
1626         "convolver()\n\n"
1627         "Creates a sound that will apply convolution to another sound.\n\n"
1628         ":arg impulseResponse: The filter with which convolve the sound.\n"
1629         ":type impulseResponse: :class:`ImpulseResponse`\n"
1630         ":arg threadPool: A thread pool used to parallelize convolution.\n"
1631         ":type threadPool: :class:`ThreadPool`\n"
1632         ":return: The created :class:`Sound` object.\n"
1633         ":rtype: :class:`Sound`");
1634
1635 static PyObject *
1636 Sound_convolver(Sound* self, PyObject* args)
1637 {
1638         PyTypeObject* type = Py_TYPE(self);
1639
1640         PyObject* object1;
1641         PyObject* object2;
1642
1643         if(!PyArg_ParseTuple(args, "OO:convolver", &object1, &object2))
1644                 return nullptr;
1645
1646         ImpulseResponseP* filter = checkImpulseResponse(object1);
1647         if(!filter)
1648                 return nullptr;
1649
1650         ThreadPoolP* threadPool = checkThreadPool(object2);
1651         if(!threadPool)
1652                 return nullptr;
1653
1654         Sound* parent;
1655         parent = (Sound*)type->tp_alloc(type, 0);
1656
1657         if(parent != nullptr)
1658         {
1659                 try
1660                 {
1661                         parent->sound = new std::shared_ptr<ISound>(new ConvolverSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ImpulseResponse>*>(filter->impulseResponse), *reinterpret_cast<std::shared_ptr<ThreadPool>*>(threadPool->threadPool)));
1662                 }
1663                 catch(Exception& e)
1664                 {
1665                         Py_DECREF(parent);
1666                         PyErr_SetString(AUDError, e.what());
1667                         return nullptr;
1668                 }
1669         }
1670
1671         return (PyObject *)parent;
1672 }
1673
1674 PyDoc_STRVAR(M_aud_Sound_binaural_doc,
1675         "convolver()\n\n"
1676         "Creates a binaural sound using another sound as source. The original sound must be mono\n\n"
1677         ":arg hrtfs: An HRTF set.\n"
1678         ":type hrtf: :class:`HRTF`\n"
1679         ":arg source: An object representing the source position of the sound.\n"
1680         ":type source: :class:`Source`\n"
1681         ":arg threadPool: A thread pool used to parallelize convolution.\n"
1682         ":type threadPool: :class:`ThreadPool`\n"
1683         ":return: The created :class:`Sound` object.\n"
1684         ":rtype: :class:`Sound`");
1685
1686 static PyObject *
1687 Sound_binaural(Sound* self, PyObject* args)
1688 {
1689         PyTypeObject* type = Py_TYPE(self);
1690
1691         PyObject* object1;
1692         PyObject* object2;
1693         PyObject* object3;
1694
1695         if(!PyArg_ParseTuple(args, "OOO:binaural", &object1, &object2, &object3))
1696                 return nullptr;
1697
1698         HRTFP* hrtfs = checkHRTF(object1);
1699         if(!hrtfs)
1700                 return nullptr;
1701
1702         SourceP* source = checkSource(object2);
1703         if(!hrtfs)
1704                 return nullptr;
1705
1706         ThreadPoolP* threadPool = checkThreadPool(object3);
1707         if(!threadPool)
1708                 return nullptr;
1709
1710         Sound* parent;
1711         parent = (Sound*)type->tp_alloc(type, 0);
1712
1713         if(parent != nullptr)
1714         {
1715                 try
1716                 {
1717                         parent->sound = new std::shared_ptr<ISound>(new BinauralSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<HRTF>*>(hrtfs->hrtf), *reinterpret_cast<std::shared_ptr<Source>*>(source->source), *reinterpret_cast<std::shared_ptr<ThreadPool>*>(threadPool->threadPool)));
1718                 }
1719                 catch(Exception& e)
1720                 {
1721                         Py_DECREF(parent);
1722                         PyErr_SetString(AUDError, e.what());
1723                         return nullptr;
1724                 }
1725         }
1726
1727         return (PyObject *)parent;
1728 }
1729
1730 #endif
1731
1732 static PyMethodDef Sound_methods[] = {
1733         {"data", (PyCFunction)Sound_data, METH_NOARGS,
1734          M_aud_Sound_data_doc
1735         },
1736         {"write", (PyCFunction)Sound_write, METH_VARARGS | METH_KEYWORDS,
1737          M_aud_Sound_write_doc
1738         },
1739         {"buffer", (PyCFunction)Sound_buffer, METH_VARARGS | METH_CLASS,
1740          M_aud_Sound_buffer_doc
1741         },
1742         {"cache", (PyCFunction)Sound_cache, METH_NOARGS,
1743          M_aud_Sound_cache_doc
1744         },
1745         {"file", (PyCFunction)Sound_file, METH_VARARGS | METH_CLASS,
1746          M_aud_Sound_file_doc
1747         },
1748         {"sawtooth", (PyCFunction)Sound_sawtooth, METH_VARARGS | METH_CLASS,
1749          M_aud_Sound_sawtooth_doc
1750         },
1751         {"silence", (PyCFunction)Sound_silence, METH_NOARGS | METH_CLASS,
1752          M_aud_Sound_silence_doc
1753         },
1754         {"sine", (PyCFunction)Sound_sine, METH_VARARGS | METH_CLASS,
1755          M_aud_Sound_sine_doc
1756         },
1757         {"square", (PyCFunction)Sound_square, METH_VARARGS | METH_CLASS,
1758          M_aud_Sound_square_doc
1759         },
1760         {"triangle", (PyCFunction)Sound_triangle, METH_VARARGS | METH_CLASS,
1761          M_aud_Sound_triangle_doc
1762         },
1763         {"accumulate", (PyCFunction)Sound_accumulate, METH_VARARGS,
1764          M_aud_Sound_accumulate_doc
1765         },
1766         {"ADSR", (PyCFunction)Sound_ADSR, METH_VARARGS,
1767          M_aud_Sound_ADSR_doc
1768         },
1769         {"delay", (PyCFunction)Sound_delay, METH_VARARGS,
1770          M_aud_Sound_delay_doc
1771         },
1772         {"envelope", (PyCFunction)Sound_envelope, METH_VARARGS,
1773          M_aud_Sound_envelope_doc
1774         },
1775         {"fadein", (PyCFunction)Sound_fadein, METH_VARARGS,
1776          M_aud_Sound_fadein_doc
1777         },
1778         {"fadeout", (PyCFunction)Sound_fadeout, METH_VARARGS,
1779          M_aud_Sound_fadeout_doc
1780         },
1781         {"filter", (PyCFunction)Sound_filter, METH_VARARGS,
1782          M_aud_Sound_filter_doc
1783         },
1784         {"highpass", (PyCFunction)Sound_highpass, METH_VARARGS,
1785          M_aud_Sound_highpass_doc
1786         },
1787         {"limit", (PyCFunction)Sound_limit, METH_VARARGS,
1788          M_aud_Sound_limit_doc
1789         },
1790         {"loop", (PyCFunction)Sound_loop, METH_VARARGS,
1791          M_aud_Sound_loop_doc
1792         },
1793         {"lowpass", (PyCFunction)Sound_lowpass, METH_VARARGS,
1794          M_aud_Sound_lowpass_doc
1795         },
1796         {"pitch", (PyCFunction)Sound_pitch, METH_VARARGS,
1797          M_aud_Sound_pitch_doc
1798         },
1799         {"rechannel", (PyCFunction)Sound_rechannel, METH_VARARGS,
1800          M_aud_Sound_rechannel_doc
1801         },
1802         {"resample", (PyCFunction)Sound_resample, METH_VARARGS,
1803          M_aud_Sound_resample_doc
1804         },
1805         {"reverse", (PyCFunction)Sound_reverse, METH_NOARGS,
1806          M_aud_Sound_reverse_doc
1807         },
1808         {"sum", (PyCFunction)Sound_sum, METH_NOARGS,
1809          M_aud_Sound_sum_doc
1810         },
1811         {"threshold", (PyCFunction)Sound_threshold, METH_VARARGS,
1812          M_aud_Sound_threshold_doc
1813         },
1814         {"volume", (PyCFunction)Sound_volume, METH_VARARGS,
1815          M_aud_Sound_volume_doc
1816         },
1817         {"join", (PyCFunction)Sound_join, METH_O,
1818          M_aud_Sound_join_doc
1819         },
1820         {"mix", (PyCFunction)Sound_mix, METH_O,
1821          M_aud_Sound_mix_doc
1822         },
1823         { "pingpong", (PyCFunction)Sound_pingpong, METH_NOARGS,
1824          M_aud_Sound_pingpong_doc
1825         },
1826         { "list", (PyCFunction)Sound_list, METH_VARARGS | METH_CLASS,
1827          M_aud_Sound_list_doc
1828         },
1829         { "mutable", (PyCFunction)Sound_mutable, METH_NOARGS,
1830          M_aud_Sound_mutable_doc
1831         },
1832         { "addSound", (PyCFunction)Sound_list_addSound, METH_O,
1833         M_aud_Sound_list_addSound_doc
1834         },
1835 #ifdef WITH_CONVOLUTION
1836         { "convolver", (PyCFunction)Sound_convolver, METH_VARARGS,
1837         M_aud_Sound_convolver_doc
1838         },
1839         { "binaural", (PyCFunction)Sound_binaural, METH_VARARGS,
1840         M_aud_Sound_binaural_doc
1841         },
1842 #endif
1843         {nullptr}  /* Sentinel */
1844 };
1845
1846 PyDoc_STRVAR(M_aud_Sound_specs_doc,
1847                          "The sample specification of the sound as a tuple with rate and channel count.");
1848
1849 static PyObject *
1850 Sound_get_specs(Sound* self, void* nothing)
1851 {
1852         try
1853         {
1854                 Specs specs = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader()->getSpecs();
1855                 return Py_BuildValue("(di)", specs.rate, specs.channels);
1856         }
1857         catch(Exception& e)
1858         {
1859                 PyErr_SetString(AUDError, e.what());
1860                 return nullptr;
1861         }
1862 }
1863
1864 PyDoc_STRVAR(M_aud_Sound_length_doc,
1865                          "The sample specification of the sound as a tuple with rate and channel count.");
1866
1867 static PyObject *
1868 Sound_get_length(Sound* self, void* nothing)
1869 {
1870         try
1871         {
1872                 int length = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader()->getLength();
1873                 return Py_BuildValue("i", length);
1874         }
1875         catch(Exception& e)
1876         {
1877                 PyErr_SetString(AUDError, e.what());
1878                 return nullptr;
1879         }
1880 }
1881
1882 static PyGetSetDef Sound_properties[] = {
1883         {(char*)"specs", (getter)Sound_get_specs, nullptr,
1884          M_aud_Sound_specs_doc, nullptr },
1885         {(char*)"length", (getter)Sound_get_length, nullptr,
1886          M_aud_Sound_length_doc, nullptr },
1887         {nullptr}  /* Sentinel */
1888 };
1889
1890 PyDoc_STRVAR(M_aud_Sound_doc,
1891                          "Sound objects are immutable and represent a sound that can be "
1892                          "played simultaneously multiple times. They are called factories "
1893                          "because they create reader objects internally that are used for "
1894                          "playback.");
1895
1896 PyTypeObject SoundType = {
1897         PyVarObject_HEAD_INIT(nullptr, 0)
1898         "aud.Sound",               /* tp_name */
1899         sizeof(Sound),             /* tp_basicsize */
1900         0,                         /* tp_itemsize */
1901         (destructor)Sound_dealloc, /* tp_dealloc */
1902         0,                         /* tp_print */
1903         0,                         /* tp_getattr */
1904         0,                         /* tp_setattr */
1905         0,                         /* tp_reserved */
1906         0,                         /* tp_repr */
1907         0,                         /* tp_as_number */
1908         0,                         /* tp_as_sequence */
1909         0,                         /* tp_as_mapping */
1910         0,                         /* tp_hash  */
1911         0,                         /* tp_call */
1912         0,                         /* tp_str */
1913         0,                         /* tp_getattro */
1914         0,                         /* tp_setattro */
1915         0,                         /* tp_as_buffer */
1916         Py_TPFLAGS_DEFAULT,        /* tp_flags */
1917         M_aud_Sound_doc,           /* tp_doc */
1918         0,                                 /* tp_traverse */
1919         0,                                 /* tp_clear */
1920         0,                                 /* tp_richcompare */
1921         0,                                 /* tp_weaklistoffset */
1922         0,                                 /* tp_iter */
1923         0,                                 /* tp_iternext */
1924         Sound_methods,             /* tp_methods */
1925         0,                         /* tp_members */
1926         Sound_properties,          /* tp_getset */
1927         0,                         /* tp_base */
1928         0,                         /* tp_dict */
1929         0,                         /* tp_descr_get */
1930         0,                         /* tp_descr_set */
1931         0,                         /* tp_dictoffset */
1932         0,                         /* tp_init */
1933         0,                         /* tp_alloc */
1934         Sound_new,                 /* tp_new */
1935 };
1936
1937 AUD_API PyObject* Sound_empty()
1938 {
1939         return SoundType.tp_alloc(&SoundType, 0);
1940 }
1941
1942 AUD_API Sound* checkSound(PyObject* sound)
1943 {
1944         if(!PyObject_TypeCheck(sound, &SoundType))
1945         {
1946                 PyErr_SetString(PyExc_TypeError, "Object is not of type Sound!");
1947                 return nullptr;
1948         }
1949
1950         return (Sound*)sound;
1951 }
1952
1953
1954 bool initializeSound()
1955 {
1956         import_array();
1957
1958         return PyType_Ready(&SoundType) >= 0;
1959 }
1960
1961
1962 void addSoundToModule(PyObject* module)
1963 {
1964         Py_INCREF(&SoundType);
1965         PyModule_AddObject(module, "Sound", (PyObject *)&SoundType);
1966 }