// 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);