Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / khotkeys / shared / sound.cpp
blob5207087adad3cdd1d900110dd4e2ec1905653e77
1 /***************************************************************************
2 * Copyright (C) 2005 by Olivier Goffart *
3 * ogoffart@kde.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "sound.h"
22 #include <QtCore/QFile>
23 #include <QtCore/QDataStream>
24 #include <kdebug.h>
29 Sound::Sound()
34 Sound::~Sound()
39 #define READ_FROM_STREAM(FORMAT,NAME) FORMAT NAME; stream >> NAME;
40 #define MAGIC(CH) { \
41 stream >> magic; \
42 if( magic != ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ) \
43 { \
44 kWarning() << "bad format " << magic << " != " << CH "\n";\
45 return;\
46 } }
48 #define ABS(X) ( (X>0) ? X : -X )
50 void Sound::load(const QString& filename)
52 kDebug() << filename;
53 data=QVector<Q_INT32>();
54 QFile file(filename);
55 if(!file.open(IO_ReadOnly))
57 kWarning() <<"unable to open file" ;
58 return;
60 QDataStream stream(&file);
61 stream.setByteOrder( QDataStream::LittleEndian );
62 Q_INT32 magic;
64 MAGIC("RIFF");
65 READ_FROM_STREAM(quint32,ChunkSize);
66 MAGIC("WAVE");
67 MAGIC("fmt ");
68 READ_FROM_STREAM(quint32,ChunkSize2);
69 READ_FROM_STREAM(Q_INT16,AudioFormat);
70 READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
71 READ_FROM_STREAM(quint32,SampleRate);
72 _fs=SampleRate;
73 READ_FROM_STREAM(quint32,ByteRate);
74 READ_FROM_STREAM(Q_UINT16,BlockAlign);
75 READ_FROM_STREAM(Q_UINT16,BitsPerSample);
76 MAGIC("data");
77 READ_FROM_STREAM(QByteArray,SoundData);
78 NumberOfChannels=1; //Wav i play are broken
80 file.close();
82 uint BytePS=BitsPerSample/8;
83 uint NumberOfSamples = (SoundData.size())/(NumberOfChannels*BytePS);
86 data.resize(NumberOfSamples);
88 // kDebug() << NumberOfSamples << " samples";
90 max=0;
91 for(unsigned long int f=0;f<NumberOfSamples;f++)
93 Q_INT32 nb=0;
94 for(uint k=0;k<BytePS;k++)
96 nb |= (SoundData[(unsigned int)(f*BytePS+k)]&0x000000FF) << (k*8);
98 if(nb & (1 << (BytePS*8 -1)) )
99 nb = nb-(1<<BytePS*8);
100 data[f]=nb;
101 if(ABS(nb)>max)
103 max=ABS(nb);
107 /* static int q=0;
108 QString name="test" + QString::number(q++) + ".wav";
109 save(name);*/
113 #define SMAGIC(CH) { stream << ( Q_INT32) ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ; }
115 void Sound::save(const QString& filename) const
117 kDebug( 1217 ) << filename << " - " << data.size() << endl;
118 QFile file(filename);
119 if(!file.open(IO_WriteOnly))
121 kWarning() <<"unable to open file" ;
122 return;
124 QDataStream stream(&file);
125 stream.setByteOrder( QDataStream::LittleEndian );
128 QByteArray SoundData(data.size()*2, '\0');
130 for(long int f=0;f<data.size();f++)
132 Q_UINT16 val= (signed short int) ( (data.at(f) * ((double)(1<<13)/(signed)max) ) );
133 SoundData[ (uint)(2*f) ]= val & 0x00FF;
134 SoundData[(uint)(2*f+1)]= (val & 0xFF00) >> 8;
136 // kDebug( 1217 ) << data.at(f) << " / " << max << " = " << val << " | " << SoundData[ 2*f ] << " "<< SoundData[ 2*f+1 ] << endl;
139 Q_UINT16 NumberOfChannels=2;
140 quint32 SampleRate=_fs;
142 SMAGIC("RIFF");
143 //READ_FROM_STREAM(quint32,ChunkSize);
144 stream << (quint32)(36+ SoundData.size());
145 SMAGIC("WAVE");
146 SMAGIC("fmt ");
147 //READ_FROM_STREAM(quint32,ChunkSize2);
148 stream << (quint32)(16);
149 //READ_FROM_STREAM(Q_INT16,AudioFormat);
150 stream << (Q_INT16)(1);
151 //READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
152 stream << (Q_UINT16)(NumberOfChannels);
153 //READ_FROM_STREAM(quint32,SampleRate);
154 stream << (quint32)(SampleRate);
155 //READ_FROM_STREAM(quint32,ByteRate);
156 stream << (quint32)(NumberOfChannels*SampleRate*16/8);
157 //READ_FROM_STREAM(Q_UINT16,BlockAlign);
158 stream << (Q_UINT16)(16/8 *NumberOfChannels);
159 //READ_FROM_STREAM(Q_UINT16,BitsPerSample);
160 stream << (Q_UINT16)(16);
161 SMAGIC("data");
162 //READ_FROM_STREAM(QByteArray,SoundData);
163 stream << SoundData;
165 file.close();
172 #if 0
173 void Sound::load(const QString& filename)
175 cout << "saout \n";
176 data=QMemArray<long unsigned int>();
177 static const int BUFFER_LEN = 4096;
179 //code from libtunepimp
180 //(wav_trm.cpp)
182 FILE *source;
183 unsigned char buffer[100], *copyBuffer;
184 unsigned int bytes;
185 unsigned long ulRIFF;
186 unsigned long ulLength;
187 unsigned long ulWAVE;
188 unsigned long ulType;
189 unsigned long ulCount;
190 unsigned long ulLimit;
191 bool haveWaveHeader = false;
192 unsigned long waveSize = 0;
193 WAVEFORMAT waveFormat;
194 int toRead;
195 mb_int64_t fileLen = 0;
197 source = fopen(filename.ascii(), "rb");
198 if (source == NULL)
200 // errorString = string("File not found");
201 // fclose(source);
202 cout << "File not found \n";
203 return;
206 fseek(source, 0, SEEK_END);
207 fileLen = ftell(source);
208 fseek(source, 0, SEEK_SET);
210 if (fread(buffer, 1, 12, source) != 12)
212 // errorString = string("File is too short");
213 cout << "File is to short \n";
214 fclose(source);
215 return ;
218 ulRIFF = (unsigned long)(((unsigned long *)buffer)[0]);
219 ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
220 ulWAVE = (unsigned long)(((unsigned long *)buffer)[2]);
222 if(ulRIFF != MAKEFOURCC('R', 'I', 'F', 'F') ||
223 ulWAVE != MAKEFOURCC('W', 'A', 'V', 'E'))
225 // errorString = strdup("File is not in WAVE format");
226 cout << "File is not WAVE \n";
227 fclose(source);
228 return ;
231 // Run through the bytes looking for the tags
232 ulCount = 0;
233 ulLimit = ulLength - 4;
234 while (ulCount < ulLimit && waveSize == 0)
236 if (fread(buffer, 1, 8, source) != 8)
238 // errorString = strdup("File is too short");
239 cout << "File is to short \n";
240 fclose(source);
241 return;
244 ulType = (unsigned long)(((unsigned long *)buffer)[0]);
245 ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
246 switch (ulType)
248 // format
249 case MAKEFOURCC('f', 'm', 't', ' '):
250 if (ulLength < sizeof(WAVEFORMAT))
252 // errorString = strdup("File is too short");
253 cout << "File is to short \n";
254 fclose(source);
255 return ;
258 if (fread(&waveFormat, 1, ulLength, source) != ulLength)
260 // errorString = strdup("File is too short");
261 cout << "File is to short \n";
262 fclose(source);
263 return ;
266 if (waveFormat.wFormatTag != WAVE_FORMAT_PCM)
268 // errorString = strdup("Unsupported WAV format");
269 cout << "Unsupported WAVE \n";
270 fclose(source);
271 return ;
273 haveWaveHeader = true;
275 ulCount += ulLength;
276 break;
278 // data
279 case MAKEFOURCC('d', 'a', 't', 'a'):
280 waveSize = ulLength;
281 break;
283 default:
284 fseek(source, ulLength, SEEK_CUR);
285 break;
291 if (!haveWaveHeader)
293 // errorString = strdup("Could not find WAV header");
294 cout << "Header nbot found \n";
295 fclose(source);
296 return ;
299 fileLen -= (mb_int64_t)ftell(source);
300 fileLen /= waveFormat.nChannels;
301 fileLen /= (waveFormat.nBlockAlign / waveFormat.nChannels);
303 fileLen /= waveFormat.nSamplesPerSec;
305 //on ne lit qu'un channel
306 //waveSize=fileLen;
307 data.resize(waveSize);
308 unsigned long pos=0;
310 cout << "Weeee "<< waveSize <<"\n";
312 copyBuffer = (unsigned char*)malloc(BUFFER_LEN);
313 if (copyBuffer == NULL)
315 // errorString = strdup("Cannot allocate buffer space.");
316 return ;
319 for(;;)
321 toRead = min(waveSize, (unsigned long)BUFFER_LEN);
322 if (toRead <= 0)
323 break;
325 bytes = fread(copyBuffer, 1, toRead, source);
326 if (bytes <= 0)
327 break;
329 for(uint f=0;f<bytes;f+=4)
331 data[pos]=(((unsigned long*)copyBuffer)[f/4]);
332 pos++;
335 waveSize -= toRead;
337 free(copyBuffer);
338 fclose(source);
340 return ;
343 #endif