changed copyright years in source files
[fegdk.git] / core / code / audio / wavfile.cpp
blob72bf47e8dfa3d0b42038d46d57f2eb811962a1c6
1 /*
2 fegdk: FE Game Development Kit
3 Copyright (C) 2001-2008 Alexey "waker" Yakovenko
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library 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 GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 Alexander Maltsev
20 keltar@users.sourceforge.net
23 #include "pch.h"
24 #include "wavfile.h"
25 #include "f_helpers.h"
26 #include "basesounddriver.h"
27 #include "f_engine.h"
29 namespace fe
32 wavFeeder::wavFeeder (wavFile *file)
34 mpFile = file;
37 void wavFeeder::call (void *data)
39 mpFile->update ();
42 wavFile::wavFile (const char *name)
43 : baseSound (name)
44 , mFeeder (this)
46 mName = name;
48 mpBuffer = NULL;
49 mpPCMOut = NULL;
50 mbEOF = false;
51 mCurrentSection = -1;
52 mpFile = NULL;
53 mHaveBytes = 0;
54 mbLooping = false;
55 mbPaused = false;
56 mVolume = 0;
57 mbPlaying = false;
59 mpFile = g_engine->getFileSystem ()->openFile (mName, FS_MODE_READ);
61 fprintf (stderr, "loading %s from disk....\n", this->name ());
63 if (mpFile)
65 // read WAV header
66 if (!mpFile->read (&mWavHeader, sizeof (wavHeader)))
68 fprintf (stderr, "WAV header not found in %s\n", this->name ());
69 mpFile->close ();
70 mpFile = NULL;
71 return;
74 // checking
75 // TODO implement it
77 if (mWavHeader.size < 2000000)
79 mbStreaming = false;
80 mpBuffer = g_engine->getSoundDriver ()->createBuffer (mWavHeader.samplesPerSecond, 16, mWavHeader.channels == 1 ? false : true, mWavHeader.dataSize, false);
81 mpPCMOut = new char[mWavHeader.dataSize];
82 mHaveBytes = mpFile->read (mpPCMOut, mWavHeader.dataSize);
83 mpBuffer->write (mpPCMOut, mWavHeader.dataSize, (mWavHeader.channels == 1) ? baseSoundDriver::fmt_mono16 : baseSoundDriver::fmt_stereo16, mWavHeader.samplesPerSecond);
84 delete[] mpPCMOut;
85 mpPCMOut = NULL;
87 if (mpFile)
89 mpFile->close ();
90 mpFile = NULL;
93 else
95 mbStreaming = true;
96 mpPCMOut = new char[buffer_size * 2];
97 mpBuffer = g_engine->getSoundDriver ()->createBuffer (mWavHeader.samplesPerSecond, 16, mWavHeader.channels == 1 ? false : true, buffer_size, true);
98 mpBuffer->setFeeder (&mFeeder);
103 wavFile::~wavFile (void)
105 stop ();
106 if (mpBuffer)
108 mpBuffer->stop ();
109 mpBuffer->release ();
110 mpBuffer = NULL;
112 if (mpPCMOut)
114 delete[] mpPCMOut;
115 mpPCMOut = NULL;
118 if (mpFile)
120 mpFile->close ();
121 mpFile = NULL;
125 void wavFile::play (bool looping)
127 if (!mpBuffer)
128 return;
130 mbLooping = looping;
131 if (mbStreaming)
133 if (isPlaying ())
135 // rewind & unpause
136 mpFile->seek (sizeof (wavHeader), SEEK_SET);
137 mbEOF = false;
139 else
140 open ();
142 else
143 mpBuffer->setLooping (mbLooping);
145 mpBuffer->play ();
146 mbPlaying = true;
149 void wavFile::stop (void)
151 if (mpBuffer)
153 mpBuffer->stop ();
154 mbPlaying = false;
156 if (mpFile)
158 mpFile->close ();
159 mpFile = NULL;
162 mHaveBytes = 0;
165 void wavFile::pause (bool onoff)
167 if (mpBuffer)
169 mpBuffer->pause (onoff);
171 mbPlaying = !onoff;
174 void wavFile::setVolume (float volume)
176 mVolume = volume;
177 if (mpBuffer)
178 mpBuffer->setVolume (volume);
181 bool wavFile::isPlaying (void) const
183 return mbPlaying;
186 int wavFile::getChannelsCount (void) const
188 return mpBuffer->getChannelsCount ();
191 void wavFile::open ()
193 mbEOF = false;
194 mCurrentSection = -1;
195 mHaveBytes = 0;
196 mpFile = g_engine->getFileSystem ()->openFile (mName, FS_MODE_READ);
197 mpFile->read (&mWavHeader, sizeof (wavHeader));
198 mpBuffer->setFeeder (&mFeeder);
201 void wavFile::update (void)
203 if (!mpFile)
204 return;
205 for (;;)
207 if (!mpBuffer)
208 break;
210 if (mbPaused)
211 break;
213 while (!mbEOF && mHaveBytes < buffer_size)
215 // read wav
216 long ret = mpFile->read (mpPCMOut + mHaveBytes, buffer_size - mHaveBytes);
217 if (ret == 0)
219 if (mbLooping)
221 // rewind
222 mpFile->seek (sizeof (wavHeader), SEEK_SET);
223 mbEOF = false;
225 else
226 mbEOF = true;
228 else if (ret < 0)
230 // error
232 else
234 mHaveBytes += ret;
238 if (mbEOF && !mbLooping)
240 stop ();
241 return;
245 if (mHaveBytes || mbEOF)
247 /* if (mEventStop)
249 DWORD signStop = WaitForSingleObject (mEventStop, 10);
250 if (signStop == WAIT_OBJECT_0 && mbEOF && !mHaveBytes)
252 stop ();
253 break;
257 if (mbEOF && !mHaveBytes)
259 break;
262 bool updated = false;
264 if (mHaveBytes < buffer_size)
266 memset (mpPCMOut + buffer_size, 0, buffer_size - mHaveBytes);
267 mHaveBytes = buffer_size;
269 int copybytes = min ((int)buffer_size, (int)mHaveBytes);
271 mpBuffer->write (mpPCMOut, copybytes, baseSoundDriver::fmt_stereo16, mWavHeader.samplesPerSecond);
273 updated = true;
275 if (updated && mHaveBytes > buffer_size)
277 memmove (mpPCMOut, &mpPCMOut[buffer_size], mHaveBytes - buffer_size);
278 mHaveBytes -= buffer_size;
280 else if (updated)
281 mHaveBytes = 0;
283 break;
287 smartPtr <baseSound> wavFile::duplicate (void)
289 return new wavFile (name ());