Audio:
[blender.git] / intern / audaspace / intern / AUD_FileWriter.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * Copyright 2009-2011 Jörg Hermann Müller
5  *
6  * This file is part of AudaSpace.
7  *
8  * Audaspace is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * AudaSpace is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Audaspace; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file audaspace/intern/AUD_FileWriter.cpp
26  *  \ingroup audaspaceintern
27  */
28
29 #ifdef WITH_FFMPEG
30 // needed for INT64_C
31 #ifndef __STDC_CONSTANT_MACROS
32 #define __STDC_CONSTANT_MACROS
33 #endif
34 #include "AUD_FFMPEGWriter.h"
35 #endif
36
37 #ifdef WITH_SNDFILE
38 #include "AUD_SndFileWriter.h"
39 #endif
40
41 #include "AUD_FileWriter.h"
42 #include "AUD_Buffer.h"
43
44 static const char* write_error = "AUD_FileWriter: File couldn't be written.";
45
46 AUD_Reference<AUD_IWriter> AUD_FileWriter::createWriter(std::string filename,AUD_DeviceSpecs specs,
47                                                                                                                 AUD_Container format, AUD_Codec codec, unsigned int bitrate)
48 {
49 #ifdef WITH_SNDFILE
50         try
51         {
52                 return new AUD_SndFileWriter(filename, specs, format, codec, bitrate);
53         }
54         catch(AUD_Exception&) {}
55 #endif
56
57 #ifdef WITH_FFMPEG
58         try
59         {
60                 return new AUD_FFMPEGWriter(filename, specs, format, codec, bitrate);
61         }
62         catch(AUD_Exception&) {}
63 #endif
64
65         AUD_THROW(AUD_ERROR_SPECS, write_error);
66 }
67
68 void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize)
69 {
70         AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(writer->getSpecs()));
71         sample_t* buf = buffer.getBuffer();
72
73         int len;
74         bool eos = false;
75         int channels = writer->getSpecs().channels;
76
77         for(unsigned int pos = 0; ((pos < length) || (length <= 0)) && !eos; pos += len)
78         {
79                 len = buffersize;
80                 if((len > length - pos) && (length > 0))
81                         len = length - pos;
82                 reader->read(len, eos, buf);
83
84                 for(int i = 0; i < len * channels; i++)
85                 {
86                         // clamping!
87                         if(buf[i] > 1)
88                                 buf[i] = 1;
89                         else if(buf[i] < -1)
90                                 buf[i] = -1;
91                 }
92
93                 writer->write(len, buf);
94         }
95 }
96
97 void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, std::vector<AUD_Reference<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize)
98 {
99         AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(reader->getSpecs()));
100         AUD_Buffer buffer2(buffersize * sizeof(sample_t));
101         sample_t* buf = buffer.getBuffer();
102         sample_t* buf2 = buffer2.getBuffer();
103
104         int len;
105         bool eos = false;
106         int channels = reader->getSpecs().channels;
107
108         for(unsigned int pos = 0; ((pos < length) || (length <= 0)) && !eos; pos += len)
109         {
110                 len = buffersize;
111                 if((len > length - pos) && (length > 0))
112                         len = length - pos;
113                 reader->read(len, eos, buf);
114
115                 for(int channel = 0; channel < channels; channel++)
116                 {
117                         for(int i = 0; i < len; i++)
118                         {
119                                 // clamping!
120                                 if(buf[i * channels + channel] > 1)
121                                         buf2[i] = 1;
122                                 else if(buf[i * channels + channel] < -1)
123                                         buf2[i] = -1;
124                                 else
125                                         buf2[i] = buf[i * channels + channel];
126                         }
127
128                         writers[channel]->write(len, buf2);
129                 }
130         }
131 }