summaryrefslogtreecommitdiffstats
path: root/audiofile_artsplugin/audiofilePlayObjectI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'audiofile_artsplugin/audiofilePlayObjectI.cpp')
-rw-r--r--audiofile_artsplugin/audiofilePlayObjectI.cpp343
1 files changed, 343 insertions, 0 deletions
diff --git a/audiofile_artsplugin/audiofilePlayObjectI.cpp b/audiofile_artsplugin/audiofilePlayObjectI.cpp
new file mode 100644
index 00000000..377a9d25
--- /dev/null
+++ b/audiofile_artsplugin/audiofilePlayObjectI.cpp
@@ -0,0 +1,343 @@
+// audiofilePlayObject
+//
+// Copyright (C) 2001 Neil Stevens <neil@qualityassistant.com>
+// Copyright (C) 2002 Rik Hemsley (rikkus) <rik@kde.org>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Except as contained in this notice, the name(s) of the author(s) shall not be
+// used in advertising or otherwise to promote the sale, use or other dealings
+// in this Software without prior written authorization from the author(s).
+
+#include "audiofilePlayObjectI.h"
+
+#include <resample.h>
+#include <soundserver.h>
+#include <convert.h>
+#include <debug.h>
+#include <math.h>
+#include <stdlib.h>
+
+namespace Arts
+{
+ class AudioFilePlayObjectRefiller : public Refiller
+ {
+ public:
+
+ AudioFilePlayObjectRefiller()
+ : fileHandle_(AF_NULL_FILEHANDLE),
+ frameSize_(0)
+ {
+ }
+
+ void setFileHandle(AFfilehandle fileHandle)
+ {
+ fileHandle_ = fileHandle;
+ }
+
+ void setFrameSize(unsigned int frameSize)
+ {
+ frameSize_ = frameSize;
+ }
+
+
+ unsigned long read(unsigned char * buffer, unsigned long len)
+ {
+ if (AF_NULL_FILEHANDLE == fileHandle_)
+ return 0;
+
+ int framesRead =
+ afReadFrames
+ (fileHandle_, AF_DEFAULT_TRACK, (void *)buffer, len / frameSize_);
+
+ if (-1 == framesRead)
+ return 0;
+
+ return framesRead * frameSize_;
+ }
+
+ private:
+
+ AFfilehandle fileHandle_;
+ unsigned int frameSize_;
+ };
+}
+
+static inline AFframecount timeToFrame(poTime time, float samplingRate)
+{
+ float seconds = time.seconds;
+ // ignoring ms
+ return (int)(floor(seconds * samplingRate));
+}
+
+static inline poTime frameToTime(AFframecount frame, float samplingRate)
+{
+ float seconds = (float)frame / samplingRate;
+ poTime time;
+ time.seconds = (long int)(floor(seconds));
+ time.ms = (long int)(floor(seconds * 1000.0) - (time.seconds * 1000.0));
+ return time;
+}
+
+audiofilePlayObjectI::audiofilePlayObjectI()
+ : audiofilePlayObject_skel()
+ , StdSynthModule()
+ , fh(AF_NULL_FILEHANDLE)
+ , channels(0)
+ , frameSize(0)
+ , sampleWidth(0)
+ , samplingRate(0)
+ , myState(posIdle)
+ , _speed(1.0)
+ , resampler(0)
+{
+ refiller = new AudioFilePlayObjectRefiller;
+ resampler = new Arts::Resampler(refiller);
+}
+
+audiofilePlayObjectI::~audiofilePlayObjectI()
+{
+ delete refiller;
+ refiller = 0;
+
+ delete resampler;
+ resampler = 0;
+
+ if (sanityCheck())
+ {
+ afCloseFile(fh);
+ fh = AF_NULL_FILEHANDLE;
+ }
+}
+
+bool audiofilePlayObjectI::loadMedia(const string &filename)
+{
+ if (sanityCheck())
+ {
+ afCloseFile(fh);
+ fh = AF_NULL_FILEHANDLE;
+ refiller->setFileHandle(fh);
+ }
+
+ fh = afOpenFile(filename.c_str(), "r", 0);
+
+ if (!sanityCheck())
+ {
+ this->filename = "";
+ return false;
+ }
+
+ this->filename = filename;
+ afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
+
+ int sampleFormat;
+
+ channels = afGetChannels(fh, AF_DEFAULT_TRACK);
+
+ afGetSampleFormat(fh, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
+
+ samplingRate = afGetRate(fh, AF_DEFAULT_TRACK);
+ frameSize = sampleWidth / 8 * channels;
+
+ arts_debug("loading wav: %s", filename.c_str());
+ arts_debug(" frame size: %d", frameSize);
+
+ resampler->setChannels(channels);
+ resampler->setBits(sampleWidth);
+ resampler->setEndianness(Arts::Resampler::littleEndian);
+
+ refiller->setFileHandle(fh);
+ refiller->setFrameSize(frameSize);
+
+ arts_debug(" channels: %d", channels);
+ arts_debug(" bits: %d",sampleWidth);
+
+ myState = posIdle;
+ return true;
+}
+
+string audiofilePlayObjectI::description()
+{
+ return "audiofilePlayObject";
+}
+
+string audiofilePlayObjectI::mediaName()
+{
+ return filename;
+}
+
+poCapabilities audiofilePlayObjectI::capabilities()
+{
+ return static_cast<poCapabilities>(capSeek | capPause);
+}
+
+poState audiofilePlayObjectI::state()
+{
+ if(!sanityCheck())
+ return posIdle;
+ else
+ return myState;
+}
+
+void audiofilePlayObjectI::play()
+{
+ myState = posPlaying;
+}
+
+void audiofilePlayObjectI::pause()
+{
+ myState = posPaused;
+}
+
+void audiofilePlayObjectI::halt()
+{
+ afSeekFrame(fh, AF_DEFAULT_TRACK, 0);
+ myState = posIdle;
+}
+
+poTime audiofilePlayObjectI::currentTime()
+{
+ if (!sanityCheck())
+ return poTime(0,0,0,"samples");
+
+ AFfileoffset offset = afTellFrame(fh, AF_DEFAULT_TRACK);
+
+ float timesec = offset / samplingRate;
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime
+ (
+ int(timesec),
+ int(timems),
+ offset,
+ "samples"
+ );
+}
+
+poTime audiofilePlayObjectI::overallTime()
+{
+ if (!sanityCheck())
+ return poTime(0, 0, 0, "samples");
+
+ AFfileoffset offset = afGetTrackBytes(fh, AF_DEFAULT_TRACK) / frameSize;
+
+ float timesec = offset / (float)samplingRate;
+ float timems = (timesec - floor(timesec)) * 1000.0;
+
+ return poTime(int(timesec), int(timems), offset, "samples");
+}
+
+void audiofilePlayObjectI::seek(const poTime &time)
+{
+ if (!sanityCheck())
+ {
+ return;
+ }
+
+ float fnewsamples = -1;
+
+ if (time.seconds != -1 && time.ms != -1)
+ {
+ float flnewtime = (float)time.seconds+((float)time.ms/1000.0);
+ fnewsamples = flnewtime * samplingRate;
+ }
+ else if (time.custom >= 0 && time.customUnit == "samples")
+ {
+ fnewsamples = time.custom;
+ }
+
+ // Avoid going past end of file.
+
+ AFfileoffset eof = afGetTrackBytes(fh, AF_DEFAULT_TRACK) / frameSize;
+
+ if (fnewsamples > (float)eof)
+ fnewsamples = (float)eof;
+
+ // Avoid going past beginning of file.
+
+ if (fnewsamples < 0)
+ fnewsamples = 0.0;
+
+ afSeekFrame(fh, AF_DEFAULT_TRACK, (unsigned long)fnewsamples);
+}
+
+void audiofilePlayObjectI::calculateBlock(unsigned long count)
+{
+ if (myState == posPlaying)
+ {
+ double speed = samplingRate / samplingRateFloat;
+
+ resampler->setStep(speed * _speed);
+ resampler->run(left, right, count);
+
+ if (resampler->underrun())
+ {
+ myState = posIdle;
+ }
+ }
+ else
+ {
+ for (unsigned long i = 0; i < count; i++)
+ {
+ left[i] = right[i] = 0;
+ }
+ }
+
+}
+
+AutoSuspendState audiofilePlayObjectI::autoSuspend()
+{
+ return asNoSuspend;
+}
+
+float audiofilePlayObjectI::speed()
+{
+ return _speed;
+}
+
+void audiofilePlayObjectI::speed(float newSpeed)
+{
+ if(newSpeed != _speed)
+ {
+ _speed = newSpeed;
+ speed_changed(_speed);
+ }
+}
+
+void audiofilePlayObjectI::start()
+{
+}
+
+void audiofilePlayObjectI::stop()
+{
+}
+
+void audiofilePlayObjectI::streamInit()
+{
+}
+
+void audiofilePlayObjectI::streamStart()
+{
+}
+
+void audiofilePlayObjectI::streamEnd()
+{
+}
+
+REGISTER_IMPLEMENTATION(audiofilePlayObjectI);
+// vim:tabstop=2:shiftwidth=2:expandtab:cinoptions=(s,U1,m1