From e2de64d6f1beb9e492daf5b886e19933c1fa41dd Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- audiofile_artsplugin/audiofilePlayObjectI.cpp | 343 ++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 audiofile_artsplugin/audiofilePlayObjectI.cpp (limited to 'audiofile_artsplugin/audiofilePlayObjectI.cpp') 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 +// Copyright (C) 2002 Rik Hemsley (rikkus) +// +// 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 +#include +#include +#include +#include +#include + +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(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 -- cgit v1.2.1