Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsound_t.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <errno.h></errno.h>
Toshihiro Shimizu 890ddd
#include <audio.h></audio.h>
Toshihiro Shimizu 890ddd
#include <unistd.h></unistd.h>
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// forward declaration
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
bool isInterfaceSupported(int deviceType, int interfaceType);
Toshihiro Shimizu 890ddd
bool setDefaultInput(TSoundInputDevice::Source type);
Toshihiro Shimizu 890ddd
bool setDefaultOutput();
Toshihiro Shimizu 890ddd
bool isChangeOutput(ULONG sampleRate);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TSoundOutputDeviceImp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ALport m_port;
Shinya Kitaoka 120a6e
  bool m_stopped;
Shinya Kitaoka 120a6e
  bool m_isPlaying;
Shinya Kitaoka 120a6e
  bool m_looped;
Shinya Kitaoka 120a6e
  TSoundTrackFormat m_currentFormat;
Shinya Kitaoka 120a6e
  std::queue<tsoundtrackp> m_queuedSoundTracks;</tsoundtrackp>
Shinya Kitaoka 120a6e
  std::set<int> m_supportedRate;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TThread::Executor m_executor;
Shinya Kitaoka 120a6e
  TThread::Mutex m_mutex;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSoundOutputDeviceImp()
Shinya Kitaoka 120a6e
      : m_stopped(false)
Shinya Kitaoka 120a6e
      , m_isPlaying(false)
Shinya Kitaoka 120a6e
      , m_looped(false)
Shinya Kitaoka 120a6e
      , m_port(NULL)
Shinya Kitaoka 120a6e
      , m_queuedSoundTracks()
Shinya Kitaoka 120a6e
      , m_supportedRate(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~TSoundOutputDeviceImp(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool doOpenDevice(const TSoundTrackFormat &format);
Shinya Kitaoka 120a6e
  void insertAllRate();
Shinya Kitaoka 120a6e
  bool verifyRate();
Shinya Kitaoka 120a6e
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format) {
Shinya Kitaoka 120a6e
  ALconfig config;
Shinya Kitaoka 120a6e
  ALpv pvbuf[3];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_currentFormat = format;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi
Shinya Kitaoka 120a6e
  pvbuf[0].param = AL_PORT_COUNT;
Shinya Kitaoka 120a6e
  pvbuf[1].param = AL_MONITOR_CTL;
Shinya Kitaoka 120a6e
  if (alGetParams(AL_DEFAULT_OUTPUT, pvbuf, 2) < 0)
Shinya Kitaoka 120a6e
    if (oserror() == AL_BAD_DEVICE_ACCESS)
Shinya Kitaoka 120a6e
      return false;  // throw TException("Could not access audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE))
Shinya Kitaoka 120a6e
    return false;  // throw TException("Speakers are not supported");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker",
Shinya Kitaoka 120a6e
                                AL_DEVICE_TYPE);
Shinya Kitaoka 120a6e
  if (!dev) return false;  // throw TException("invalid device speakers");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  pvbuf[0].param   = AL_DEFAULT_OUTPUT;
Shinya Kitaoka 120a6e
  pvbuf[0].value.i = dev;
Shinya Kitaoka 120a6e
  alSetParams(AL_SYSTEM, pvbuf, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  config = alNewConfig();
Shinya Kitaoka 120a6e
  // qui devo metterci gli altoparlanti e poi setto i valori per il default
Shinya Kitaoka 120a6e
  // output
Shinya Kitaoka 120a6e
  pvbuf[0].param     = AL_RATE;
Shinya Kitaoka 120a6e
  pvbuf[0].value.ll  = alDoubleToFixed((double)format.m_sampleRate);
Shinya Kitaoka 120a6e
  pvbuf[1].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pvbuf[1].value.ptr = buf;
Shinya Kitaoka 120a6e
  pvbuf[1].sizeIn    = 8;
Shinya Kitaoka 120a6e
  pvbuf[2].param     = AL_INTERFACE;
Shinya Kitaoka 120a6e
  pvbuf[2].value.i   = AL_SPEAKER_IF_TYPE;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 3) < 0) return false;
Shinya Kitaoka 120a6e
  // throw TException("Unable to set params for output device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (alSetChannels(config, format.m_channelCount) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int bytePerSample = format.m_bitPerSample >> 3;
Shinya Kitaoka 120a6e
  switch (bytePerSample) {
Shinya Kitaoka 120a6e
  case 3:
Shinya Kitaoka 120a6e
    bytePerSample++;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetWidth(config, bytePerSample) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_port = alOpenPort("AudioOutput", "w", config);
Shinya Kitaoka 120a6e
  if (!m_port) return false;  // throw TException("Could not open audio port.");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  alFreeConfig(config);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundOutputDeviceImp::insertAllRate() {
Shinya Kitaoka 120a6e
  m_supportedRate.insert(8000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(11025);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(16000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(22050);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(32000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(44100);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(48000);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDeviceImp::verifyRate() {
Shinya Kitaoka 120a6e
  // Sample Rate
Shinya Kitaoka 120a6e
  ALparamInfo pinfo;
Shinya Kitaoka 120a6e
  int ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_RATE, &pinfo);
Shinya Kitaoka 120a6e
  if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) {
Shinya Kitaoka 120a6e
    int min = (int)alFixedToDouble(pinfo.min.ll);
Shinya Kitaoka 120a6e
    int max = (int)alFixedToDouble(pinfo.max.ll);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
    for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it)
Shinya Kitaoka 120a6e
      if (*it < min || *it > max) m_supportedRate.erase(*it);
Shinya Kitaoka 120a6e
    if (m_supportedRate.end() == m_supportedRate.begin()) return false;
Shinya Kitaoka 120a6e
  } else if (ret == AL_BAD_PARAM)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class PlayTask : public TThread::Runnable {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TSoundOutputDeviceImp *m_devImp;
Shinya Kitaoka 120a6e
  TSoundTrackP m_sndtrack;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  PlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st)
Shinya Kitaoka 120a6e
      : TThread::Runnable(), m_devImp(devImp), m_sndtrack(st){};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~PlayTask(){};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void run();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlayTask::run() {
Shinya Kitaoka 120a6e
  int leftToPlay = m_sndtrack->getSampleCount();
Shinya Kitaoka 120a6e
  int i          = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_devImp->m_port ||
Shinya Kitaoka 120a6e
      (m_devImp->m_currentFormat != m_sndtrack->getFormat()) ||
Shinya Kitaoka 120a6e
      isChangeOutput(m_sndtrack->getSampleRate()))
Shinya Kitaoka 120a6e
    if (!m_devImp->doOpenDevice(m_sndtrack->getFormat())) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  while ((leftToPlay > 0) && m_devImp->m_isPlaying) {
Shinya Kitaoka 120a6e
    int fillable = alGetFillable(m_devImp->m_port);
Shinya Kitaoka 120a6e
    if (!fillable) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (fillable < leftToPlay) {
Shinya Kitaoka 120a6e
      alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i),
Shinya Kitaoka 120a6e
                    fillable);
Shinya Kitaoka 120a6e
      // ricorda getSampleSize restituisce m_sampleSize che comprende gia'
Shinya Kitaoka 120a6e
      // la moltiplicazione per il numero dei canali
Shinya Kitaoka 120a6e
      i += fillable * m_sndtrack->getSampleSize();
Shinya Kitaoka 120a6e
      leftToPlay -= fillable;
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i),
Shinya Kitaoka 120a6e
                    leftToPlay);
Shinya Kitaoka 120a6e
      leftToPlay = 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_devImp->m_stopped) {
Shinya Kitaoka 120a6e
    while (ALgetfilled(m_devImp->m_port) > 0) sginap(1);
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TThread::ScopedLock sl(m_devImp->m_mutex);
Shinya Kitaoka 120a6e
      if (!m_devImp->m_looped) m_devImp->m_queuedSoundTracks.pop();
Shinya Kitaoka 120a6e
      if (m_devImp->m_queuedSoundTracks.empty()) {
Shinya Kitaoka 120a6e
        m_devImp->m_isPlaying = false;
Shinya Kitaoka 120a6e
        m_devImp->m_stopped   = true;
Shinya Kitaoka 120a6e
        m_devImp->m_looped    = false;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        m_devImp->m_executor.addTask(
Shinya Kitaoka 120a6e
            new PlayTask(m_devImp, m_devImp->m_queuedSoundTracks.front()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    alDiscardFrames(m_devImp->m_port, alGetFilled(m_devImp->m_port));
Shinya Kitaoka 120a6e
    while (!m_devImp->m_queuedSoundTracks.empty())
Shinya Kitaoka 120a6e
      m_devImp->m_queuedSoundTracks.pop();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) {
Shinya Kitaoka 120a6e
  if (!setDefaultOutput())
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice,
Shinya Kitaoka 120a6e
                                "Speaker not supported");
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    supportsVolume();
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_imp->insertAllRate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundOutputDevice::~TSoundOutputDevice() {
Shinya Kitaoka 120a6e
  close();
Shinya Kitaoka 120a6e
  delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::installed() {
Shinya Kitaoka 120a6e
  if (alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, 0, 0, 0, 0) <= 0)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::open(const TSoundTrackP &st) {
Shinya Kitaoka 120a6e
  if (!m_imp->doOpenDevice(st->getFormat()))
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(
Shinya Kitaoka 120a6e
        TSoundDeviceException::UnableOpenDevice,
Shinya Kitaoka 120a6e
        "Problem to open the output device or set some params");
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::close() {
Shinya Kitaoka 120a6e
  stop();
Shinya Kitaoka 120a6e
  if (m_imp->m_port) alClosePort(m_imp->m_port);
Shinya Kitaoka 120a6e
  m_imp->m_port = NULL;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1,
Shinya Kitaoka 120a6e
                              bool loop, bool scrubbing) {
Shinya Kitaoka 120a6e
  if (!st->getSampleCount()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
    if (m_imp->m_looped)
Shinya Kitaoka 120a6e
      throw TSoundDeviceException(
Shinya Kitaoka 120a6e
          TSoundDeviceException::Busy,
Shinya Kitaoka 120a6e
          "Unable to queue another playback when the sound player is looping");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->m_isPlaying = true;
Shinya Kitaoka 120a6e
    m_imp->m_stopped   = false;
Shinya Kitaoka 120a6e
    m_imp->m_looped    = loop;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt;
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    fmt = getPreferredFormat(st->getFormat());
Shinya Kitaoka 120a6e
    if (fmt != st->getFormat()) {
Shinya Kitaoka 120a6e
      throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                  "Unsupported Format");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(s1 >= s0);
Shinya Kitaoka 120a6e
  TSoundTrackP subTrack = st->extract(s0, s1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // far partire il thread
Shinya Kitaoka 120a6e
  if (m_imp->m_queuedSoundTracks.empty()) {
Shinya Kitaoka 120a6e
    m_imp->m_queuedSoundTracks.push(subTrack);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_imp->m_executor.addTask(new PlayTask(m_imp, subTrack));
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    m_imp->m_queuedSoundTracks.push(subTrack);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundOutputDevice::stop() {
Shinya Kitaoka 120a6e
  if (!m_imp->m_isPlaying) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  m_imp->m_isPlaying = false;
Shinya Kitaoka 120a6e
  m_imp->m_stopped   = true;
Shinya Kitaoka 120a6e
  m_imp->m_looped    = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TSoundOutputDevice::getVolume() {
Shinya Kitaoka 120a6e
  ALpv pv[1];
Shinya Kitaoka 120a6e
  ALfixed value[2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    supportsVolume();
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  pv[0].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pv[0].value.ptr = value;
Shinya Kitaoka 120a6e
  pv[0].sizeIn    = 8;
Shinya Kitaoka 120a6e
  alGetParams(AL_DEFAULT_OUTPUT, pv, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double val =
Shinya Kitaoka 120a6e
      (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) /
Shinya Kitaoka 120a6e
      8.05;
Shinya Kitaoka 120a6e
  return val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::setVolume(double volume) {
Shinya Kitaoka 120a6e
  ALpv pv[1];
Shinya Kitaoka 120a6e
  ALfixed value[2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    supportsVolume();
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double val = -60. + 8.05 * volume;
Shinya Kitaoka 120a6e
  value[0]   = alDoubleToFixed(val);
Shinya Kitaoka 120a6e
  value[1]   = alDoubleToFixed(val);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  pv[0].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pv[0].value.ptr = value;
Shinya Kitaoka 120a6e
  pv[0].sizeIn    = 8;
Shinya Kitaoka 120a6e
  if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0) return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::supportsVolume() {
Shinya Kitaoka 120a6e
  ALparamInfo pinfo;
Shinya Kitaoka 120a6e
  int ret;
Shinya Kitaoka 120a6e
  ret        = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo);
Shinya Kitaoka 120a6e
  double min = alFixedToDouble(pinfo.min.ll);
Shinya Kitaoka 120a6e
  double max = alFixedToDouble(pinfo.max.ll);
Shinya Kitaoka 120a6e
  if ((ret != -1) && (min != max) && (max != 0.0))
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0)))
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnableVolume,
Shinya Kitaoka 120a6e
                                "It is impossible to chamge setting of volume");
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
                                "Output device is not accessible");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::isPlaying() const { return m_imp->m_isPlaying; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundOutputDevice::isLooping() {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  return m_imp->m_looped;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundOutputDevice::setLooping(bool loop) {
Shinya Kitaoka 120a6e
  TThread::ScopedLock sl(m_imp->m_mutex);
Shinya Kitaoka 120a6e
  m_imp->m_looped = loop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(ULONG sampleRate,
Shinya Kitaoka 120a6e
                                                         int channelCount,
Shinya Kitaoka 120a6e
                                                         int bitPerSample) {
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt;
Shinya Kitaoka 120a6e
  int ret;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_imp->verifyRate())
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                "There isn't any support rate");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_imp->m_supportedRate.find((int)sampleRate) ==
Shinya Kitaoka 120a6e
      m_imp->m_supportedRate.end()) {
Shinya Kitaoka 120a6e
    std::set<int>::iterator it =</int>
Shinya Kitaoka 120a6e
        m_imp->m_supportedRate.lower_bound((int)sampleRate);
Shinya Kitaoka 120a6e
    if (it == m_imp->m_supportedRate.end()) {
Shinya Kitaoka 120a6e
      it = std::max_element(m_imp->m_supportedRate.begin(),
Shinya Kitaoka 120a6e
                            m_imp->m_supportedRate.end());
Shinya Kitaoka 120a6e
      if (it != m_imp->m_supportedRate.end())
Shinya Kitaoka 120a6e
        sampleRate = *(m_imp->m_supportedRate.rbegin());
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                    "There isn't a supported rate");
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      sampleRate = *it;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int value;
Shinya Kitaoka 120a6e
  ALvalue vals[32];
Shinya Kitaoka 120a6e
  if ((ret = alQueryValues(AL_DEFAULT_OUTPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0)
Shinya Kitaoka 120a6e
    for (int i = 0; i < ret; ++i) value = vals[i].i;
Shinya Kitaoka 120a6e
  else if (oserror() == AL_BAD_PARAM)
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(
Shinya Kitaoka 120a6e
        TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
        "It is impossible ask for the max numbers of channels supported");
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(
Shinya Kitaoka 120a6e
        TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
        "It is impossibile information about ouput device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (value > 2) value = 2;
Shinya Kitaoka 120a6e
  if (channelCount > value)
Shinya Kitaoka 120a6e
    channelCount = value;
Shinya Kitaoka 120a6e
  else if (channelCount <= 0)
Shinya Kitaoka 120a6e
    channelCount = 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bitPerSample <= 8)
Shinya Kitaoka 120a6e
    bitPerSample = 8;
Shinya Kitaoka 120a6e
  else if (bitPerSample <= 16)
Shinya Kitaoka 120a6e
    bitPerSample = 16;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    bitPerSample = 24;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  fmt.m_bitPerSample = bitPerSample;
Shinya Kitaoka 120a6e
  fmt.m_channelCount = channelCount;
Shinya Kitaoka 120a6e
  fmt.m_sampleRate   = sampleRate;
Shinya Kitaoka 120a6e
  fmt.m_signedSample = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(
Shinya Kitaoka 120a6e
    const TSoundTrackFormat &format) {
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    return getPreferredFormat(format.m_sampleRate, format.m_channelCount,
Shinya Kitaoka 120a6e
                              format.m_bitPerSample);
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//                REGISTRAZIONE
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TSoundInputDeviceImp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ALport m_port;
Shinya Kitaoka 120a6e
  bool m_stopped;
Shinya Kitaoka 120a6e
  bool m_isRecording;
Shinya Kitaoka 120a6e
  bool m_oneShotRecording;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TINT32 m_recordedSampleCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  vector<char *=""> m_recordedBlocks;</char>
Shinya Kitaoka 120a6e
  vector<int> m_samplePerBlocks;</int>
Shinya Kitaoka 120a6e
  TSoundTrackFormat m_currentFormat;
Shinya Kitaoka 120a6e
  TSoundTrackP m_st;
Shinya Kitaoka 120a6e
  std::set<int> m_supportedRate;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TThread::Executor m_executor;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TSoundInputDeviceImp()
Shinya Kitaoka 120a6e
      : m_stopped(false)
Shinya Kitaoka 120a6e
      , m_isRecording(false)
Shinya Kitaoka 120a6e
      , m_port(NULL)
Shinya Kitaoka 120a6e
      , m_recordedBlocks()
Shinya Kitaoka 120a6e
      , m_samplePerBlocks()
Shinya Kitaoka 120a6e
      , m_recordedSampleCount(0)
Shinya Kitaoka 120a6e
      , m_oneShotRecording(false)
Shinya Kitaoka 120a6e
      , m_st(0)
Shinya Kitaoka 120a6e
      , m_supportedRate(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~TSoundInputDeviceImp(){};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool doOpenDevice(const TSoundTrackFormat &format,
Shinya Kitaoka 120a6e
                    TSoundInputDevice::Source devType);
Shinya Kitaoka 120a6e
  void insertAllRate();
Shinya Kitaoka 120a6e
  bool verifyRate();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format,
Shinya Kitaoka 120a6e
                                        TSoundInputDevice::Source devType) {
Shinya Kitaoka 120a6e
  ALconfig config;
Shinya Kitaoka 120a6e
  ALpv pvbuf[2];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_currentFormat = format;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi
Shinya Kitaoka 120a6e
  pvbuf[0].param = AL_PORT_COUNT;
Shinya Kitaoka 120a6e
  pvbuf[1].param = AL_MONITOR_CTL;
Shinya Kitaoka 120a6e
  if (alGetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0)
Shinya Kitaoka 120a6e
    if (oserror() == AL_BAD_DEVICE_ACCESS)
Shinya Kitaoka 120a6e
      return false;  // throw TException("Could not access audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  config = alNewConfig();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!setDefaultInput(devType))
Shinya Kitaoka 120a6e
    return false;  // throw TException("Could not set the input device
Shinya Kitaoka 120a6e
                   // specified");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pvbuf[0].param    = AL_RATE;
Shinya Kitaoka 120a6e
  pvbuf[0].value.ll = alDoubleToFixed(format.m_sampleRate);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ALfixed buf[2]     = {alDoubleToFixed(0), alDoubleToFixed(0)};
Shinya Kitaoka 120a6e
  pvbuf[1].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pvbuf[1].value.ptr = buf;
Shinya Kitaoka 120a6e
  pvbuf[1].sizeIn    = 8;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Problem to set params ");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetChannels(config, format.m_channelCount) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int bytePerSample = format.m_bitPerSample >> 3;
Shinya Kitaoka 120a6e
  switch (bytePerSample) {
Shinya Kitaoka 120a6e
  case 3:
Shinya Kitaoka 120a6e
    bytePerSample++;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  if (alSetWidth(config, bytePerSample) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  alSetDevice(config, AL_DEFAULT_INPUT);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_port = alOpenPort("AudioInput", "r", config);
Shinya Kitaoka 120a6e
  if (!m_port) return false;  // throw TException("Could not open audio port.");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  alFreeConfig(config);
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundInputDeviceImp::insertAllRate() {
Shinya Kitaoka 120a6e
  m_supportedRate.insert(8000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(11025);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(16000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(22050);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(32000);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(44100);
Shinya Kitaoka 120a6e
  m_supportedRate.insert(48000);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundInputDeviceImp::verifyRate() {
Shinya Kitaoka 120a6e
  // Sample Rate
Shinya Kitaoka 120a6e
  ALparamInfo pinfo;
Shinya Kitaoka 120a6e
  int ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_RATE, &pinfo);
Shinya Kitaoka 120a6e
  if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) {
Shinya Kitaoka 120a6e
    int min = (int)alFixedToDouble(pinfo.min.ll);
Shinya Kitaoka 120a6e
    int max = (int)alFixedToDouble(pinfo.max.ll);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
    for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it)
Shinya Kitaoka 120a6e
      if (*it < min || *it > max) m_supportedRate.erase(*it);
Shinya Kitaoka 120a6e
    if (m_supportedRate.end() == m_supportedRate.begin()) return false;
Shinya Kitaoka 120a6e
  } else if (ret == AL_BAD_PARAM)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class RecordTask : public TThread::Runnable {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TSoundInputDeviceImp *m_devImp;
Shinya Kitaoka 120a6e
  int m_ByteToSample;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  RecordTask(TSoundInputDeviceImp *devImp, int numByte)
Shinya Kitaoka 120a6e
      : TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ~RecordTask(){};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void run();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RecordTask::run() {
Shinya Kitaoka 120a6e
  TINT32 byteRecordedSample = 0;
Shinya Kitaoka 120a6e
  int filled                = alGetFilled(m_devImp->m_port);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_devImp->m_oneShotRecording) {
Shinya Kitaoka 120a6e
    char *rawData = m_devImp->m_recordedBlocks.front();
Shinya Kitaoka 120a6e
    int sampleSize;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if ((m_devImp->m_currentFormat.m_bitPerSample >> 3) == 3)
Shinya Kitaoka 120a6e
      sampleSize = 4;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      sampleSize = (m_devImp->m_currentFormat.m_bitPerSample >> 3);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    sampleSize *= m_devImp->m_currentFormat.m_channelCount;
Shinya Kitaoka 120a6e
    while ((byteRecordedSample <= (m_ByteToSample - filled * sampleSize)) &&
Shinya Kitaoka 120a6e
           m_devImp->m_isRecording) {
Shinya Kitaoka 120a6e
      alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample),
Shinya Kitaoka 120a6e
                   filled);
Shinya Kitaoka 120a6e
      byteRecordedSample += filled * sampleSize;
Shinya Kitaoka 120a6e
      filled = alGetFilled(m_devImp->m_port);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_devImp->m_isRecording) {
Shinya Kitaoka 120a6e
      alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample),
Shinya Kitaoka 120a6e
                   (m_ByteToSample - byteRecordedSample) / sampleSize);
Shinya Kitaoka 120a6e
      while (alGetFillable(m_devImp->m_port) > 0) sginap(1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    while (m_devImp->m_isRecording) {
Shinya Kitaoka 120a6e
      filled = alGetFilled(m_devImp->m_port);
Shinya Kitaoka 120a6e
      if (filled > 0) {
Shinya Kitaoka 120a6e
        char *dataBuffer = new char[filled * m_ByteToSample];
Shinya Kitaoka 120a6e
        m_devImp->m_recordedBlocks.push_back(dataBuffer);
Shinya Kitaoka 120a6e
        m_devImp->m_samplePerBlocks.push_back(filled * m_ByteToSample);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        alReadFrames(m_devImp->m_port, (void *)dataBuffer, filled);
Shinya Kitaoka 120a6e
        m_devImp->m_recordedSampleCount += filled;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    while (alGetFillable(m_devImp->m_port) > 0) sginap(1);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  alClosePort(m_devImp->m_port);
Shinya Kitaoka 120a6e
  m_devImp->m_port    = 0;
Shinya Kitaoka 120a6e
  m_devImp->m_stopped = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundInputDevice::~TSoundInputDevice() {
Shinya Kitaoka 120a6e
  if (m_imp->m_port) alClosePort(m_imp->m_port);
Shinya Kitaoka 120a6e
  delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundInputDevice::installed() {
Shinya Kitaoka 120a6e
  if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <= 0) return false;
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundInputDevice::record(const TSoundTrackFormat &format,
Shinya Kitaoka 120a6e
                               TSoundInputDevice::Source type) {
Shinya Kitaoka 120a6e
  if (m_imp->m_isRecording == true)
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::Busy,
Shinya Kitaoka 120a6e
                                "Just another recoding is in progress");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_recordedBlocks.clear();
Shinya Kitaoka 120a6e
  m_imp->m_samplePerBlocks.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // registra creando una nuova traccia
Shinya Kitaoka 120a6e
  m_imp->m_oneShotRecording = false;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!setDefaultInput(type))
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice,
Shinya Kitaoka 120a6e
                                "Error to set the input device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->insertAllRate();
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    fmt = getPreferredFormat(format);
Shinya Kitaoka 120a6e
    if (fmt != format) {
Shinya Kitaoka 120a6e
      throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                  "Unsupported Format");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_imp->m_port) m_imp->doOpenDevice(format, type);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_currentFormat       = format;
Shinya Kitaoka 120a6e
  m_imp->m_isRecording         = true;
Shinya Kitaoka 120a6e
  m_imp->m_stopped             = false;
Shinya Kitaoka 120a6e
  m_imp->m_recordedSampleCount = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int bytePerSample = format.m_bitPerSample >> 3;
Shinya Kitaoka 120a6e
  switch (bytePerSample) {
Shinya Kitaoka 120a6e
  case 3:
Shinya Kitaoka 120a6e
    bytePerSample++;
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  bytePerSample *= format.m_channelCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // far partire il thread
Shinya Kitaoka 120a6e
  /*TRecordThread *recordThread = new TRecordThread(m_imp, bytePerSample);
Shinya Kitaoka 120a6e
  if (!recordThread)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
  m_imp->m_isRecording = false;
Shinya Kitaoka 120a6e
  m_imp->m_stopped = true;
Shinya Kitaoka 120a6e
throw TSoundDeviceException(
Shinya Kitaoka 120a6e
TSoundDeviceException::UnablePrepare,
Shinya Kitaoka 120a6e
"Unable to create the recording thread");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
recordThread->start();*/
Shinya Kitaoka 120a6e
  m_imp->m_executor.addTask(new RecordTask(m_imp, bytePerSample));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSoundInputDevice::record(const TSoundTrackP &st,
Shinya Kitaoka 120a6e
                               TSoundInputDevice::Source type) {
Shinya Kitaoka 120a6e
  if (m_imp->m_isRecording == true)
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::Busy,
Shinya Kitaoka 120a6e
                                "Just another recoding is in progress");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_recordedBlocks.clear();
Shinya Kitaoka 120a6e
  m_imp->m_samplePerBlocks.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!setDefaultInput(type))
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice,
Shinya Kitaoka 120a6e
                                "Error to set the input device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->insertAllRate();
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    fmt = getPreferredFormat(st->getFormat());
Shinya Kitaoka 120a6e
    if (fmt != st->getFormat()) {
Shinya Kitaoka 120a6e
      throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                  "Unsupported Format");
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_imp->m_port)
Shinya Kitaoka 120a6e
    if (!m_imp->doOpenDevice(st->getFormat(), type))
Shinya Kitaoka 120a6e
      throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice,
Shinya Kitaoka 120a6e
                                  "Unable to open input device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Sovrascive un'intera o parte di traccia gia' esistente
Shinya Kitaoka 120a6e
  m_imp->m_oneShotRecording    = true;
Shinya Kitaoka 120a6e
  m_imp->m_currentFormat       = st->getFormat();
Shinya Kitaoka 120a6e
  m_imp->m_isRecording         = true;
Shinya Kitaoka 120a6e
  m_imp->m_stopped             = false;
Shinya Kitaoka 120a6e
  m_imp->m_recordedSampleCount = 0;
Shinya Kitaoka 120a6e
  m_imp->m_st                  = st;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_recordedBlocks.push_back((char *)st->getRawData());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int totByteToSample = st->getSampleCount() * st->getSampleSize();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // far partire il thread
Shinya Kitaoka 120a6e
  /*TRecordThread *recordThread = new TRecordThread(m_imp, totByteToSample);
Shinya Kitaoka 120a6e
  if (!recordThread)
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
  m_imp->m_isRecording = false;
Shinya Kitaoka 120a6e
  m_imp->m_stopped = true;
Shinya Kitaoka 120a6e
throw TSoundDeviceException(
Shinya Kitaoka 120a6e
TSoundDeviceException::UnablePrepare,
Shinya Kitaoka 120a6e
"Unable to create the recording thread");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
recordThread->start();*/
Shinya Kitaoka 120a6e
  m_imp->m_executor.addTask(new RecordTask(m_imp, totByteToSample));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackP TSoundInputDevice::stop() {
Shinya Kitaoka 120a6e
  TSoundTrackP st;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_imp->m_isRecording)
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnablePrepare,
Shinya Kitaoka 120a6e
                                "No recording process is in execution");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  alDiscardFrames(m_imp->m_port, alGetFilled(m_imp->m_port));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (!m_imp->m_stopped) sginap(1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_imp->m_oneShotRecording)
Shinya Kitaoka 120a6e
    st = m_imp->m_st;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    st = TSoundTrack::create(m_imp->m_currentFormat,
Shinya Kitaoka 120a6e
                             m_imp->m_recordedSampleCount);
Shinya Kitaoka 120a6e
    TINT32 bytesCopied = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) {
Shinya Kitaoka 120a6e
      memcpy((void *)(st->getRawData() + bytesCopied),
Shinya Kitaoka 120a6e
             m_imp->m_recordedBlocks[i], m_imp->m_samplePerBlocks[i]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      delete[] m_imp->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      bytesCopied += m_imp->m_samplePerBlocks[i];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_imp->m_samplePerBlocks.clear();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return st;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
double TSoundInputDevice::getVolume() {
Shinya Kitaoka 120a6e
  ALpv pv[1];
Shinya Kitaoka 120a6e
  ALfixed value[2];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    supportsVolume();
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  pv[0].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pv[0].value.ptr = value;
Shinya Kitaoka 120a6e
  pv[0].sizeIn    = 8;
Shinya Kitaoka 120a6e
  alGetParams(AL_DEFAULT_INPUT, pv, 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double val =
Shinya Kitaoka 120a6e
      (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) /
Shinya Kitaoka 120a6e
      8.05;
Shinya Kitaoka 120a6e
  return val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundInputDevice::setVolume(double volume) {
Shinya Kitaoka 120a6e
  ALpv pv[1];
Shinya Kitaoka 120a6e
  ALfixed value[2];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    supportsVolume();
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double val = -60. + 8.05 * volume;
Shinya Kitaoka 120a6e
  value[0]   = alDoubleToFixed(val);
Shinya Kitaoka 120a6e
  value[1]   = alDoubleToFixed(val);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pv[0].param     = AL_GAIN;
Shinya Kitaoka 120a6e
  pv[0].value.ptr = value;
Shinya Kitaoka 120a6e
  pv[0].sizeIn    = 8;
Shinya Kitaoka 120a6e
  alSetParams(AL_DEFAULT_INPUT, pv, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundInputDevice::supportsVolume() {
Shinya Kitaoka 120a6e
  ALparamInfo pinfo;
Shinya Kitaoka 120a6e
  int ret;
Shinya Kitaoka 120a6e
  ret        = alGetParamInfo(AL_DEFAULT_INPUT, AL_GAIN, &pinfo);
Shinya Kitaoka 120a6e
  double min = alFixedToDouble(pinfo.min.ll);
Shinya Kitaoka 120a6e
  double max = alFixedToDouble(pinfo.max.ll);
Shinya Kitaoka 120a6e
  if ((ret != -1) && (min != max) && (max != 0.0))
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0)))
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnableVolume,
Shinya Kitaoka 120a6e
                                "It is impossible to chamge setting of volume");
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
                                "Output device is not accessible");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(ULONG sampleRate,
Shinya Kitaoka 120a6e
                                                        int channelCount,
Shinya Kitaoka 120a6e
                                                        int bitPerSample) {
Shinya Kitaoka 120a6e
  TSoundTrackFormat fmt;
Shinya Kitaoka 120a6e
  int ret;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_imp->verifyRate())
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                "There isn't any support rate");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_imp->m_supportedRate.find((int)sampleRate) ==
Shinya Kitaoka 120a6e
      m_imp->m_supportedRate.end()) {
Shinya Kitaoka 120a6e
    std::set<int>::iterator it =</int>
Shinya Kitaoka 120a6e
        m_imp->m_supportedRate.lower_bound((int)sampleRate);
Shinya Kitaoka 120a6e
    if (it == m_imp->m_supportedRate.end()) {
Shinya Kitaoka 120a6e
      it = std::max_element(m_imp->m_supportedRate.begin(),
Shinya Kitaoka 120a6e
                            m_imp->m_supportedRate.end());
Shinya Kitaoka 120a6e
      if (it != m_imp->m_supportedRate.end())
Shinya Kitaoka 120a6e
        sampleRate = *(m_imp->m_supportedRate.rbegin());
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat,
Shinya Kitaoka 120a6e
                                    "There isn't a supported rate");
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      sampleRate = *it;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int value;
Shinya Kitaoka 120a6e
  ALvalue vals[32];
Shinya Kitaoka 120a6e
  if ((ret = alQueryValues(AL_DEFAULT_INPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0)
Shinya Kitaoka 120a6e
    for (int i = 0; i < ret; ++i) value = vals[i].i;
Shinya Kitaoka 120a6e
  else if (oserror() == AL_BAD_PARAM)
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(
Shinya Kitaoka 120a6e
        TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
        "It is impossible ask for the max nembers of channels supported");
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(
Shinya Kitaoka 120a6e
        TSoundDeviceException::NoMixer,
Shinya Kitaoka 120a6e
        "It is impossibile information about ouput device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (value > 2) value = 2;
Shinya Kitaoka 120a6e
  if (channelCount > value)
Shinya Kitaoka 120a6e
    channelCount = value;
Shinya Kitaoka 120a6e
  else if (channelCount <= 0)
Shinya Kitaoka 120a6e
    channelCount = 1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bitPerSample <= 8)
Shinya Kitaoka 120a6e
    bitPerSample = 8;
Shinya Kitaoka 120a6e
  else if (bitPerSample <= 16)
Shinya Kitaoka 120a6e
    bitPerSample = 16;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    bitPerSample = 24;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  fmt.m_bitPerSample = bitPerSample;
Shinya Kitaoka 120a6e
  fmt.m_channelCount = channelCount;
Shinya Kitaoka 120a6e
  fmt.m_sampleRate   = sampleRate;
Shinya Kitaoka 120a6e
  fmt.m_signedSample = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(
Shinya Kitaoka 120a6e
    const TSoundTrackFormat &format) {
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    return getPreferredFormat(format.m_sampleRate, format.m_channelCount,
Shinya Kitaoka 120a6e
                              format.m_bitPerSample);
Shinya Kitaoka 120a6e
  } catch (TSoundDeviceException &e) {
Shinya Kitaoka 120a6e
    throw TSoundDeviceException(e.getType(), e.getMessage());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TSoundInputDevice::isRecording() { return m_imp->m_isRecording; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//******************************************************************************
Shinya Kitaoka d1f6c4
//						funzioni per l'interazione con
Shinya Kitaoka d1f6c4
// la
Shinya Kitaoka d1f6c4
// libreria
Shinya Kitaoka 38fd86
// audio
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//******************************************************************************
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
bool isInterfaceSupported(int deviceType, int interfaceType) {
Shinya Kitaoka 120a6e
  ALvalue vals[16];
Shinya Kitaoka 120a6e
  int devNum;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if ((devNum = alQueryValues(AL_SYSTEM, deviceType, vals, 16, 0, 0)) > 0) {
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    for (i = 0; i < devNum; ++i) {
Shinya Kitaoka 120a6e
      ALpv quals[2];
Shinya Kitaoka 120a6e
      quals[0].param   = AL_TYPE;
Shinya Kitaoka 120a6e
      quals[0].value.i = interfaceType;
Shinya Kitaoka 120a6e
      if (alQueryValues(vals[i].i, AL_INTERFACE, 0, 0, quals, 1) > 0)
Shinya Kitaoka 120a6e
        return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool setDefaultInput(TSoundInputDevice::Source type) {
Shinya Kitaoka 120a6e
  string label;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  switch (type) {
Shinya Kitaoka 120a6e
  case TSoundInputDevice::LineIn:
Shinya Kitaoka 120a6e
    label = "Line In";
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  case TSoundInputDevice::DigitalIn:
Shinya Kitaoka 120a6e
    label = "AES Input";
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    label = "Microphone";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int dev =
Shinya Kitaoka 120a6e
      alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_DEVICE_TYPE);
Shinya Kitaoka 120a6e
  if (!dev) return false;  // throw TException("Error to set input device");
Shinya Kitaoka 120a6e
  int itf;
Shinya Kitaoka 120a6e
  if (itf = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(),
Shinya Kitaoka 120a6e
                                AL_INTERFACE_TYPE)) {
Shinya Kitaoka 120a6e
    ALpv p;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    p.param   = AL_INTERFACE;
Shinya Kitaoka 120a6e
    p.value.i = itf;
Shinya Kitaoka 120a6e
    if (alSetParams(dev, &p, 1) < 0 || p.sizeOut < 0)
Shinya Kitaoka 120a6e
      return false;  // throw TException("Error to set input device");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ALpv param;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  param.param   = AL_DEFAULT_INPUT;
Shinya Kitaoka 120a6e
  param.value.i = dev;
Shinya Kitaoka 120a6e
  if (alSetParams(AL_SYSTEM, ¶m, 1) < 0)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Error to set input device");
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool setDefaultOutput() {
Shinya Kitaoka 120a6e
  ALpv pvbuf[1];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE))
Shinya Kitaoka 120a6e
    return false;  // throw TException("Speakers are not supported");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker",
Shinya Kitaoka 120a6e
                                AL_DEVICE_TYPE);
Shinya Kitaoka 120a6e
  if (!dev) return false;  // throw TException("invalid device speakers");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  pvbuf[0].param   = AL_DEFAULT_OUTPUT;
Shinya Kitaoka 120a6e
  pvbuf[0].value.i = dev;
Shinya Kitaoka 120a6e
  alSetParams(AL_SYSTEM, pvbuf, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // qui devo metterci gli altoparlanti e poi setto i valori per il default
Shinya Kitaoka 120a6e
  // output
Shinya Kitaoka 120a6e
  pvbuf[0].param   = AL_INTERFACE;
Shinya Kitaoka 120a6e
  pvbuf[0].value.i = AL_SPEAKER_IF_TYPE;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 1) < 0)
Shinya Kitaoka 120a6e
    return false;  // throw TException("Unable to set output device params");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// return the indexes of all input device of a particular type
Shinya Kitaoka 120a6e
list<int> getInputDevice(int deviceType) {</int>
Shinya Kitaoka 120a6e
  ALvalue vals[16];
Shinya Kitaoka 120a6e
  ALpv quals[1];
Shinya Kitaoka 120a6e
  list<int> devList;</int>
Shinya Kitaoka 120a6e
  int devNum;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  quals[0].param   = AL_TYPE;
Shinya Kitaoka 120a6e
  quals[0].value.i = deviceType;
Shinya Kitaoka 120a6e
  if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals,
Shinya Kitaoka 120a6e
                              1)) > 0) {
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    for (i = 0; i < devNum; ++i) {
Shinya Kitaoka 120a6e
      int itf;
Shinya Kitaoka 120a6e
      ALvalue val[16];
Shinya Kitaoka 120a6e
      if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, 0, 0)) > 0) {
Shinya Kitaoka 120a6e
        int j;
Shinya Kitaoka 120a6e
        for (j = 0; j < itf; ++j) devList.push_back(vals[j].i);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return devList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// return the indexes of all input device of a particular type and interface
Shinya Kitaoka 120a6e
list<int> getInputDevice(int deviceType, int itfType) {</int>
Shinya Kitaoka 120a6e
  ALvalue vals[16];
Shinya Kitaoka 120a6e
  ALpv quals[1];
Shinya Kitaoka 120a6e
  list<int> devList;</int>
Shinya Kitaoka 120a6e
  int devNum;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  quals[0].param   = AL_TYPE;
Shinya Kitaoka 120a6e
  quals[0].value.i = deviceType;
Shinya Kitaoka 120a6e
  if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals,
Shinya Kitaoka 120a6e
                              1)) > 0) {
Shinya Kitaoka 120a6e
    int i;
Shinya Kitaoka 120a6e
    for (i = 0; i < devNum; ++i) {
Shinya Kitaoka 120a6e
      int itf;
Shinya Kitaoka 120a6e
      ALvalue val[16];
Shinya Kitaoka 120a6e
      quals[0].param   = AL_TYPE;
Shinya Kitaoka 120a6e
      quals[0].value.i = itfType;
Shinya Kitaoka 120a6e
      if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, quals, 1)) > 0) {
Shinya Kitaoka 120a6e
        int j;
Shinya Kitaoka 120a6e
        for (j = 0; j < itf; ++j) devList.push_back(vals[j].i);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return devList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
string getResourceLabel(int resourceID) {
Shinya Kitaoka 120a6e
  ALpv par[1];
Shinya Kitaoka 120a6e
  char l[32];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  par[0].param     = AL_LABEL;
Shinya Kitaoka 120a6e
  par[0].value.ptr = l;
Shinya Kitaoka 120a6e
  par[0].sizeIn    = 32;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  alGetParams(resourceID, par, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return string(l);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// verify the samplerate of the select device is changed from another
Shinya Kitaoka 120a6e
// application
Shinya Kitaoka 120a6e
bool isChangeOutput(ULONG sampleRate) {
Shinya Kitaoka 120a6e
  ALpv par[2];
Shinya Kitaoka 120a6e
  char l[32];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  par[0].param     = AL_LABEL;
Shinya Kitaoka 120a6e
  par[0].value.ptr = l;
Shinya Kitaoka 120a6e
  par[0].sizeIn    = 32;
Shinya Kitaoka 120a6e
  par[1].param     = AL_RATE;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  alGetParams(AL_DEFAULT_OUTPUT, par, 2);
Shinya Kitaoka 120a6e
  if ((strcmp(l, "Analog Out") != 0) ||
Shinya Kitaoka 120a6e
      (alFixedToDouble(par[1].value.ll) != sampleRate))
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}