summaryrefslogtreecommitdiffstats
path: root/flow/audiosubsys.cc
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2020-12-06 19:28:06 +0900
committerMichele Calgaro <[email protected]>2020-12-06 19:28:06 +0900
commit00d4f92b717fbcbed6f9eee361975d6ee5380d59 (patch)
tree043b5970d66e539e1fbf6dde03440d6569e34c4e /flow/audiosubsys.cc
parent2f53bfe61c8ee78ff36ac6c66ae714b01e407b33 (diff)
downloadarts-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.cc645
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();
- }
-}