diff options
author | Michele Calgaro <[email protected]> | 2020-12-06 19:28:06 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2020-12-06 19:28:06 +0900 |
commit | 00d4f92b717fbcbed6f9eee361975d6ee5380d59 (patch) | |
tree | 043b5970d66e539e1fbf6dde03440d6569e34c4e /flow/audiosubsys.cc | |
parent | 2f53bfe61c8ee78ff36ac6c66ae714b01e407b33 (diff) | |
download | arts-00d4f92b717fbcbed6f9eee361975d6ee5380d59.tar.gz arts-00d4f92b717fbcbed6f9eee361975d6ee5380d59.zip |
Renaming of files in preparation for code style tools.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'flow/audiosubsys.cc')
-rw-r--r-- | flow/audiosubsys.cc | 645 |
1 files changed, 0 insertions, 645 deletions
diff --git a/flow/audiosubsys.cc b/flow/audiosubsys.cc deleted file mode 100644 index 46b10e6..0000000 --- a/flow/audiosubsys.cc +++ /dev/null @@ -1,645 +0,0 @@ - /* - - Copyright (C) 2000 Stefan Westerfeld - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/stat.h> - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> // Needed on some systems. -#endif - -#ifdef HAVE_SYS_SOUNDCARD_H -#include <sys/soundcard.h> -#endif - -#include <assert.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <iostream> -#include <algorithm> -#include <cstring> - -#include "debug.h" -#include "audiosubsys.h" -#include "audioio.h" - -#define DEFAULT_DEVICE_NAME "/dev/dsp" - -#undef DEBUG_WAVEFORM -#ifdef DEBUG_WAVEFORM -#include <fstream> -#endif - -using namespace std; -using namespace Arts; - -//--- automatic startup class - -static AudioSubSystemStart aStart; - -void AudioSubSystemStart::startup() -{ - _instance = new AudioSubSystem(); -} - -void AudioSubSystemStart::shutdown() -{ - delete _instance; -} - -//--- AudioSubSystemPrivate data - -class Arts::AudioSubSystemPrivate -{ -public: -#ifdef DEBUG_WAVEFORM - ofstream plotfile; -#endif - AudioIO *audioIO; - string audioIOName; - bool audioIOInit; - - unsigned int adjustDuplexOffsetIndex; - int adjustDuplexOffset[4]; - int adjustDuplexCount; -}; - -//--- AudioSubSystem implementation - -AudioSubSystem *AudioSubSystem::the() -{ - return aStart.the(); -} - -const char *AudioSubSystem::error() -{ - return _error.c_str(); -} - -AudioSubSystem::AudioSubSystem() -{ - d = new AudioSubSystemPrivate; -#ifdef DEBUG_WAVEFORM - d->plotfile.open( "/dev/shm/audiosubsystem.plot" ); -#endif - d->audioIO = 0; - d->audioIOInit = false; - - _running = false; - consumer = 0; - producer = 0; - fragment_buffer = 0; -} - -AudioSubSystem::~AudioSubSystem() -{ - delete d->audioIO; - delete d; -} - -bool AudioSubSystem::attachProducer(ASProducer *producer) -{ - assert(producer); - if(this->producer) return false; - - this->producer = producer; - return true; -} - -bool AudioSubSystem::attachConsumer(ASConsumer *consumer) -{ - assert(consumer); - if(this->consumer) return false; - - this->consumer = consumer; - return true; -} - -void AudioSubSystem::detachProducer() -{ - assert(producer); - producer = 0; - - if(_running) close(); -} - -void AudioSubSystem::detachConsumer() -{ - assert(consumer); - consumer = 0; - - if(_running) close(); -} - -/* initially creates default AudioIO */ -void AudioSubSystem::initAudioIO() -{ - /* auto detect */ - if(!d->audioIOInit) - { - string bestName; - int bestValue = 0; - - arts_debug("autodetecting driver: "); - for(int i = 0; i < AudioIO::queryAudioIOCount(); i++) - { - string name = AudioIO::queryAudioIOParamStr(i, AudioIO::name); - AudioIO *aio = AudioIO::createAudioIO(name.c_str()); - int value = aio->getParam(AudioIO::autoDetect); - - arts_debug(" - %s: %d", name.c_str(), value); - if(value > bestValue) - { - bestName = name; - bestValue = value; - } - delete aio; - } - if(bestValue) - { - arts_debug("... which means we'll default to %s", bestName.c_str()); - audioIO(bestName); - } - else - { - arts_debug("... nothing we could use as default found"); - } - } -} - -void AudioSubSystem::audioIO(const string& audioIO) -{ - if(d->audioIO) - delete d->audioIO; - - d->audioIOName = audioIO; - d->audioIO = AudioIO::createAudioIO(audioIO.c_str()); - d->audioIOInit = true; -} - -string AudioSubSystem::audioIO() -{ - initAudioIO(); - - return d->audioIOName; -} - -void AudioSubSystem::deviceName(const string& deviceName) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParamStr(AudioIO::deviceName, deviceName.c_str()); -} - -string AudioSubSystem::deviceName() -{ - initAudioIO(); - if(!d->audioIO) return ""; - - return d->audioIO->getParamStr(AudioIO::deviceName); -} - -void AudioSubSystem::fragmentCount(int fragmentCount) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParam(AudioIO::fragmentCount, fragmentCount); -} - -int AudioSubSystem::fragmentCount() -{ - initAudioIO(); - if(!d->audioIO) return 0; - - return d->audioIO->getParam(AudioIO::fragmentCount); -} - -void AudioSubSystem::fragmentSize(int fragmentSize) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParam(AudioIO::fragmentSize, fragmentSize); -} - -int AudioSubSystem::fragmentSize() -{ - initAudioIO(); - if(!d->audioIO) return 0; - - return d->audioIO->getParam(AudioIO::fragmentSize); -} - -void AudioSubSystem::samplingRate(int samplingRate) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParam(AudioIO::samplingRate, samplingRate); -} - -int AudioSubSystem::samplingRate() -{ - initAudioIO(); - if(!d->audioIO) return 0; - - return d->audioIO->getParam(AudioIO::samplingRate); -} - -void AudioSubSystem::channels(int channels) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParam(AudioIO::channels, channels); -} - -int AudioSubSystem::channels() -{ - initAudioIO(); - if(!d->audioIO) return 0; - - return d->audioIO->getParam(AudioIO::channels); -} - -void AudioSubSystem::format(int format) -{ - initAudioIO(); - if(!d->audioIO) return; - - d->audioIO->setParam(AudioIO::format, format); -} - -int AudioSubSystem::format() -{ - initAudioIO(); - if(!d->audioIO) return 0; - - return d->audioIO->getParam(AudioIO::format); -} - -int AudioSubSystem::bits() -{ - int _format = format(); - arts_assert(_format == 0 || _format == 8 || _format == 16 || _format == 17 || _format == 32); - return (_format & (32 | 16 | 8)); -} - -void AudioSubSystem::fullDuplex(bool fullDuplex) -{ - initAudioIO(); - if(!d->audioIO) return; - - int direction = fullDuplex?3:2; - d->audioIO->setParam(AudioIO::direction, direction); -} - -bool AudioSubSystem::fullDuplex() -{ - initAudioIO(); - if(!d->audioIO) return false; - - return d->audioIO->getParam(AudioIO::direction) == 3; -} - -int AudioSubSystem::selectReadFD() -{ - initAudioIO(); - if(!d->audioIO) return false; - - return d->audioIO->getParam(AudioIO::selectReadFD); -} - -int AudioSubSystem::selectWriteFD() -{ - initAudioIO(); - if(!d->audioIO) return false; - - return d->audioIO->getParam(AudioIO::selectWriteFD); -} - -bool AudioSubSystem::check() -{ - bool ok = open(); - - if(ok) close(); - return ok; -} - -bool AudioSubSystem::open() -{ - assert(!_running); - - initAudioIO(); - if(!d->audioIO) - { - if(d->audioIOName.empty()) - _error = "couldn't auto detect which audio I/O method to use"; - else - _error = "unable to select '"+d->audioIOName+"' style audio I/O"; - return false; - } - - if(d->audioIO->open()) - { - _running = true; - - _fragmentSize = d->audioIO->getParam(AudioIO::fragmentSize); - _fragmentCount = d->audioIO->getParam(AudioIO::fragmentCount); - - // allocate global buffer to do I/O - assert(fragment_buffer == 0); - fragment_buffer = new char[_fragmentSize]; - - d->adjustDuplexCount = 0; - return true; - } - else - { - _error = d->audioIO->getParamStr(AudioIO::lastError); - return false; - } -} - -void AudioSubSystem::close() -{ - assert(_running); - assert(d->audioIO); - - d->audioIO->close(); - - wBuffer.clear(); - rBuffer.clear(); - - _running = false; - if(fragment_buffer) - { - delete[] fragment_buffer; - fragment_buffer = 0; - } -} - -bool AudioSubSystem::running() -{ - return _running; -} - -void AudioSubSystem::handleIO(int type) -{ - assert(d->audioIO); - - if(type & ioRead) - { - int len = d->audioIO->read(fragment_buffer,_fragmentSize); - - if(len > 0) - { - if(rBuffer.size() < _fragmentSize * _fragmentCount * bits() / 8 * channels()) - { - rBuffer.write(len,fragment_buffer); -#ifdef DEBUG_WAVEFORM - float * end = (float *)(fragment_buffer + len); - float * floatbuffer = (float *)fragment_buffer; - while(floatbuffer < end) - { - d->plotfile << *floatbuffer++ << "\n"; - ++floatbuffer; - } -#endif - } - else - { - arts_debug( "AudioSubSystem: rBuffer is too full" ); - } - } - } - - if(type & ioWrite) - { - /* - * make sure that we have a fragment full of data at least - */ -Rewrite: - while(wBuffer.size() < _fragmentSize) - { - long wbsz = wBuffer.size(); - producer->needMore(); - - if(wbsz == wBuffer.size()) - { - /* - * Even though we asked the client to supply more - * data, he didn't give us more. So we can't supply - * output data as well. Bad luck. Might produce a - * buffer underrun - but we can't help here. - */ - arts_info("full duplex: no more data available (underrun)"); - return; - } - } - - /* - * look how much we really can write without blocking - */ - int space = d->audioIO->getParam(AudioIO::canWrite); - int can_write = min(space, _fragmentSize); - - if(can_write > 0) - { - /* - * ok, so write it (as we checked that our buffer has enough data - * to do so and the soundcardbuffer has enough data to handle this - * write, nothing can go wrong here) - */ - int rSize = wBuffer.read(can_write,fragment_buffer); - assert(rSize == can_write); - - int len = d->audioIO->write(fragment_buffer,can_write); - if(len != can_write) - arts_fatal("AudioSubSystem::handleIO: write failed\n" - "len = %d, can_write = %d, errno = %d (%s)\n\n" - "This might be a sound hardware/driver specific problem" - " (see aRts FAQ)",len,can_write,errno,strerror(errno)); - - if(fullDuplex()) - { - /* - * if we're running full duplex, here is a good place to check - * for full duplex drift - */ - d->adjustDuplexCount += can_write; - if(d->adjustDuplexCount > samplingRate()) - { - adjustDuplexBuffers(); - d->adjustDuplexCount = 0; - } - } - } - - // If we can write a fragment more, then do so right now: - if (space >= _fragmentSize*2) goto Rewrite; - } - - assert((type & ioExcept) == 0); -} - -void AudioSubSystem::read(void *buffer, int size) -{ - /* if not enough data can be read, produce some */ - while(rBuffer.size() < size) - adjustInputBuffer(1); - - /* finally, just take the data out of the input buffer */ - int rSize = rBuffer.read(size,buffer); - assert(rSize == size); -} - -void AudioSubSystem::write(void *buffer, int size) -{ - wBuffer.write(size,buffer); -} - -float AudioSubSystem::outputDelay() -{ - int fsize = _fragmentSize; - int fcount = _fragmentCount; - - if(fsize > 0 && fcount > 0) // not all AudioIO classes need to support this - { - double hardwareBuffer = fsize * fcount; - double freeOutputSpace = d->audioIO->getParam(AudioIO::canWrite); - double playSpeed = channels() * samplingRate() * (bits() / 8); - - return (hardwareBuffer - freeOutputSpace) / playSpeed; - } - else return 0.0; -} - -void AudioSubSystem::adjustDuplexBuffers() -{ - int fsize = _fragmentSize; - int fcount = _fragmentCount; - - if(fsize > 0 && fcount > 0) // not all AudioIO classes need to support this - { - int bound = 2; //max(fcount/2, 1); - int optimalOffset = fsize * (fcount + bound); - int minOffset = fsize * fcount; - int maxOffset = fsize * (fcount + 2 * bound); - - int canRead = d->audioIO->getParam(AudioIO::canRead); - if(canRead < 0) - { - arts_warning("AudioSubSystem::adjustDuplexBuffers: canRead < 0?"); - canRead = 0; - } - - int canWrite = d->audioIO->getParam(AudioIO::canWrite); - if(canWrite < 0) - { - arts_warning("AudioSubSystem::adjustDuplexBuffers: canWrite < 0?"); - canWrite = 0; - } - - int currentOffset = rBuffer.size() + wBuffer.size() - + canRead + max((fsize * fcount) - canWrite, 0); - - d->adjustDuplexOffset[d->adjustDuplexOffsetIndex++ & 3] = currentOffset; - if(d->adjustDuplexOffsetIndex <= 4) return; - - int avgOffset; - avgOffset = d->adjustDuplexOffset[0] - + d->adjustDuplexOffset[1] - + d->adjustDuplexOffset[2] - + d->adjustDuplexOffset[3]; - avgOffset /= 4; - - /* - printf("offset: %d avg %d min %d opt %d max %d\r", currentOffset, - avgOffset, minOffset, optimalOffset, maxOffset); - fflush(stdout); - */ - if(minOffset <= avgOffset && avgOffset <= maxOffset) - return; - - d->adjustDuplexOffsetIndex = 0; - int adjust = (optimalOffset - currentOffset) / _fragmentSize; - arts_debug("AudioSubSystem::adjustDuplexBuffers(%d)", adjust); - } -} - -void AudioSubSystem::adjustInputBuffer(int count) -{ - if(format() == 8) - { - memset( fragment_buffer, 0x80, _fragmentSize ); - } - else - { - memset( fragment_buffer, 0, _fragmentSize ); - } - - while(count > 0 && rBuffer.size() < _fragmentSize * _fragmentCount * 4) - { - rBuffer.write(_fragmentSize, fragment_buffer); -#ifdef DEBUG_WAVEFORM - float * end = (float *)(fragment_buffer + _fragmentSize); - float * floatbuffer = (float *)fragment_buffer; - while(floatbuffer < end) - { - d->plotfile << *floatbuffer++ << "\n"; - ++floatbuffer; - } -#endif - count--; - } - - while(count < 0 && rBuffer.size() >= _fragmentSize) - { - rBuffer.read(_fragmentSize, fragment_buffer); - count++; - } -} - -void AudioSubSystem::emergencyCleanup() -{ - if(producer || consumer) - { - fprintf(stderr, "AudioSubSystem::emergencyCleanup\n"); - - if(producer) - detachProducer(); - if(consumer) - detachConsumer(); - } -} |