Exemplo n.º 1
0
void CPulseAEStream::SetVolume(float volume)
{
  if (!m_Initialized)
    return;

  if (!pa_threaded_mainloop_in_thread(m_MainLoop))
    pa_threaded_mainloop_lock(m_MainLoop);

  if (volume > 0.f)
  {
    m_Volume = volume;
    pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_Volume * m_MaxVolume));

    pa_cvolume_set(&m_ChVolume, m_SampleSpec.channels, paVolume);
  } 
  else
    pa_cvolume_mute(&m_ChVolume,m_SampleSpec.channels);

  pa_operation *op = pa_context_set_sink_input_volume(m_Context, pa_stream_get_index(m_Stream), &m_ChVolume, NULL, NULL);

  if (op == NULL)
    CLog::Log(LOGERROR, "PulseAudio: Failed to set volume");
  else
    pa_operation_unref(op);

  if (!pa_threaded_mainloop_in_thread(m_MainLoop))
    pa_threaded_mainloop_unlock(m_MainLoop);
}
Exemplo n.º 2
0
int main(int argc, char *argv[]) {
    pa_mempool *pool;
    pa_sample_spec a, b;
    pa_cvolume v;

    pa_log_set_level(PA_LOG_DEBUG);

    pa_assert_se(pool = pa_mempool_new(FALSE, 0));

    a.channels = b.channels = 1;
    a.rate = b.rate = 44100;

    v.channels = a.channels;
    v.values[0] = pa_sw_volume_from_linear(0.5);

    for (a.format = 0; a.format < PA_SAMPLE_MAX; a.format ++) {
        for (b.format = 0; b.format < PA_SAMPLE_MAX; b.format ++) {
            pa_resampler *forth, *back;
            pa_memchunk i, j, k;

            printf("=== %s -> %s -> %s -> /2\n",
                   pa_sample_format_to_string(a.format),
                   pa_sample_format_to_string(b.format),
                   pa_sample_format_to_string(a.format));

            pa_assert_se(forth = pa_resampler_new(pool, &a, NULL, &b, NULL, PA_RESAMPLER_AUTO, 0));
            pa_assert_se(back = pa_resampler_new(pool, &b, NULL, &a, NULL, PA_RESAMPLER_AUTO, 0));

            i.memblock = generate_block(pool, &a);
            i.length = pa_memblock_get_length(i.memblock);
            i.index = 0;
            pa_resampler_run(forth, &i, &j);
            pa_resampler_run(back, &j, &k);

            printf("before:  ");
            dump_block(&a, &i);
            printf("after :  ");
            dump_block(&b, &j);
            printf("reverse: ");
            dump_block(&a, &k);

            pa_memblock_unref(j.memblock);
            pa_memblock_unref(k.memblock);

            pa_volume_memchunk(&i, &a, &v);
            printf("volume:  ");
            dump_block(&a, &i);

            pa_memblock_unref(i.memblock);

            pa_resampler_free(forth);
            pa_resampler_free(back);
        }
    }

    pa_mempool_free(pool);

    return 0;
}
Exemplo n.º 3
0
void PulseAudioInput::SetGain(long m_gain)
{
  pa_cvolume v;
  v.values[0] = pa_sw_volume_from_linear(m_gain);
  pa_cvolume_set(&v, 2, v.values[0]);
  //      pa_volume_t gain = pa_sw_volume_from_linear(m_gain);
  //      pa_cvolume_set(mp_vol, 1, gain);
  return;
}
Exemplo n.º 4
0
int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
    pa_volume_t v;

    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {

        double dB = pa_sw_volume_to_dB(v);
        double f = pa_sw_volume_to_linear(v);

        printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n",
               v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));

    }

    return 0;
}
Exemplo n.º 5
0
pa_volume_t pa_sw_volume_from_dB(double dB) {
    if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
        return PA_VOLUME_MUTED;

    return pa_sw_volume_from_linear(dB_to_linear(dB));
}
Exemplo n.º 6
0
bool CPulseAESound::Initialize()
{
  /* we dont re-init the wav loader in PA as PA handles the samplerate */
  if (!m_wavLoader.IsValid())
    return false;

  m_sampleSpec.format   = PA_SAMPLE_FLOAT32NE;
  m_sampleSpec.rate     = m_wavLoader.GetSampleRate();
  m_sampleSpec.channels = m_wavLoader.GetChannelLayout().Count();

  if (!pa_sample_spec_valid(&m_sampleSpec))
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Invalid sample spec");
    return false;
  }

  struct pa_channel_map map;
  map.channels = m_sampleSpec.channels;
  switch (map.channels)
  {
    case 1:
      map.map[0] = PA_CHANNEL_POSITION_MONO;
      break;

    case 2:
      map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
      map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
      break;

    default:
      CLog::Log(LOGERROR, "CPulseAESound::Initialize - We do not yet support multichannel sounds");
      return false;
  }

  m_maxVolume     = CAEFactory::GetEngine()->GetVolume();
  m_volume        = 1.0f;
  pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_volume * m_maxVolume));
  pa_cvolume_set(&m_chVolume, m_sampleSpec.channels, paVolume);

  pa_threaded_mainloop_lock(m_mainLoop);
  if ((m_stream = pa_stream_new(m_context, m_pulseName.c_str(), &m_sampleSpec, &map)) == NULL)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Could not create a stream");
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  pa_stream_set_state_callback(m_stream, CPulseAESound::StreamStateCallback, this);
  pa_stream_set_write_callback(m_stream, CPulseAESound::StreamWriteCallback, this);

  if (pa_stream_connect_upload(m_stream, m_wavLoader.GetFrameCount() * pa_frame_size(&m_sampleSpec)) != 0)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Could not initialize the stream");
    pa_stream_disconnect(m_stream);
    m_stream = NULL;
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  /* check if the stream failed */
  if (pa_stream_get_state(m_stream) == PA_STREAM_FAILED)
  {
    CLog::Log(LOGERROR, "CPulseAESound::Initialize - Waited for the stream but it failed");
    pa_stream_disconnect(m_stream);
    m_stream = NULL;
    pa_threaded_mainloop_unlock(m_mainLoop);
    return false;
  }

  pa_threaded_mainloop_unlock(m_mainLoop);
  return true;
}
Exemplo n.º 7
0
CPulseAEStream::CPulseAEStream(pa_context *context, pa_threaded_mainloop *mainLoop, enum AEDataFormat format, unsigned int sampleRate, CAEChannelInfo channelLayout, unsigned int options) : m_fader(this)
{
  ASSERT(channelLayout.Count());
  m_Destroyed = false;
  m_Initialized = false;
  m_Paused = false;

  m_Stream = NULL;
  m_Context = context;
  m_MainLoop = mainLoop;

  m_format = format;
  m_sampleRate = sampleRate;
  m_channelLayout = channelLayout;
  m_options = options;

  m_DrainOperation = NULL;
  m_slave = NULL;

  pa_threaded_mainloop_lock(m_MainLoop);

  m_SampleSpec.channels = channelLayout.Count();
  m_SampleSpec.rate = m_sampleRate;

  switch (m_format)
  {
    case AE_FMT_U8    : m_SampleSpec.format = PA_SAMPLE_U8; break;
    case AE_FMT_S16NE : m_SampleSpec.format = PA_SAMPLE_S16NE; break;
    case AE_FMT_S16LE : m_SampleSpec.format = PA_SAMPLE_S16LE; break;
    case AE_FMT_S16BE : m_SampleSpec.format = PA_SAMPLE_S16BE; break;
    case AE_FMT_S24NE3: m_SampleSpec.format = PA_SAMPLE_S24NE; break;
    case AE_FMT_S24NE4: m_SampleSpec.format = PA_SAMPLE_S24_32NE; break;
    case AE_FMT_S32NE : m_SampleSpec.format = PA_SAMPLE_S32NE; break;
    case AE_FMT_S32LE : m_SampleSpec.format = PA_SAMPLE_S32LE; break;
    case AE_FMT_S32BE : m_SampleSpec.format = PA_SAMPLE_S32BE; break;
    case AE_FMT_FLOAT : m_SampleSpec.format = PA_SAMPLE_FLOAT32NE; break;
#if PA_CHECK_VERSION(1,0,0)
    case AE_FMT_DTS   :
    case AE_FMT_EAC3  :
    case AE_FMT_AC3   : m_SampleSpec.format = PA_SAMPLE_S16NE; break;
#endif

    default:
      CLog::Log(LOGERROR, "PulseAudio: Invalid format %i", format);
      pa_threaded_mainloop_unlock(m_MainLoop);
      m_format = AE_FMT_INVALID;
      return;
  }

  if (!pa_sample_spec_valid(&m_SampleSpec))
  {
    CLog::Log(LOGERROR, "PulseAudio: Invalid sample spec");
    pa_threaded_mainloop_unlock(m_MainLoop);
    Destroy();
    return /*false*/;
  }

  m_frameSize = pa_frame_size(&m_SampleSpec);

  struct pa_channel_map map;
  map.channels = m_channelLayout.Count();

  for (unsigned int ch = 0; ch < m_channelLayout.Count(); ++ch)
    switch(m_channelLayout[ch])
    {
      case AE_CH_NULL: break;
      case AE_CH_MAX : break;
      case AE_CH_RAW : break;
      case AE_CH_FL  : map.map[ch] = PA_CHANNEL_POSITION_FRONT_LEFT           ; break;
      case AE_CH_FR  : map.map[ch] = PA_CHANNEL_POSITION_FRONT_RIGHT          ; break;
      case AE_CH_FC  : map.map[ch] = PA_CHANNEL_POSITION_FRONT_CENTER         ; break;
      case AE_CH_BC  : map.map[ch] = PA_CHANNEL_POSITION_REAR_CENTER          ; break;
      case AE_CH_BL  : map.map[ch] = PA_CHANNEL_POSITION_REAR_LEFT            ; break;
      case AE_CH_BR  : map.map[ch] = PA_CHANNEL_POSITION_REAR_RIGHT           ; break;
      case AE_CH_LFE : map.map[ch] = PA_CHANNEL_POSITION_LFE                  ; break;
      case AE_CH_FLOC: map.map[ch] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ; break;
      case AE_CH_FROC: map.map[ch] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; break;
      case AE_CH_SL  : map.map[ch] = PA_CHANNEL_POSITION_SIDE_LEFT            ; break;
      case AE_CH_SR  : map.map[ch] = PA_CHANNEL_POSITION_SIDE_RIGHT           ; break;
      case AE_CH_TC  : map.map[ch] = PA_CHANNEL_POSITION_TOP_CENTER           ; break;
      case AE_CH_TFL : map.map[ch] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT       ; break;
      case AE_CH_TFR : map.map[ch] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT      ; break;
      case AE_CH_TFC : map.map[ch] = PA_CHANNEL_POSITION_TOP_CENTER           ; break;
      case AE_CH_TBL : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_LEFT        ; break;
      case AE_CH_TBR : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT       ; break;
      case AE_CH_TBC : map.map[ch] = PA_CHANNEL_POSITION_TOP_REAR_CENTER      ; break;
      default: break;
    }

  m_MaxVolume     = CAEFactory::GetEngine()->GetVolume();
  m_Volume        = 1.0f;
  pa_volume_t paVolume = pa_sw_volume_from_linear((double)(m_Volume * m_MaxVolume));
  pa_cvolume_set(&m_ChVolume, m_SampleSpec.channels, paVolume);

#if PA_CHECK_VERSION(1,0,0)
  pa_format_info *info[1];
  info[0] = pa_format_info_new();
  switch(m_format)
  {
    case AE_FMT_DTS : info[0]->encoding = PA_ENCODING_DTS_IEC61937 ; break;
    case AE_FMT_EAC3: info[0]->encoding = PA_ENCODING_EAC3_IEC61937; break;
    case AE_FMT_AC3 : info[0]->encoding = PA_ENCODING_AC3_IEC61937 ; break;
    default:          info[0]->encoding = PA_ENCODING_PCM          ; break;
  }
  pa_format_info_set_rate         (info[0], m_SampleSpec.rate);
  pa_format_info_set_channels     (info[0], m_SampleSpec.channels);
  pa_format_info_set_channel_map  (info[0], &map);
  pa_format_info_set_sample_format(info[0], m_SampleSpec.format);
  m_Stream = pa_stream_new_extended(m_Context, "audio stream", info, 1, NULL);
  pa_format_info_free(info[0]);
#else
  m_Stream = pa_stream_new(m_Context, "audio stream", &m_SampleSpec, &map);
#endif

  if (m_Stream == NULL)
  {
    CLog::Log(LOGERROR, "PulseAudio: Could not create a stream");
    pa_threaded_mainloop_unlock(m_MainLoop);
    Destroy();
    return /*false*/;
  }

  pa_stream_set_state_callback(m_Stream, CPulseAEStream::StreamStateCallback, this);
  pa_stream_set_write_callback(m_Stream, CPulseAEStream::StreamRequestCallback, this);
  pa_stream_set_latency_update_callback(m_Stream, CPulseAEStream::StreamLatencyUpdateCallback, this);
  pa_stream_set_underflow_callback(m_Stream, CPulseAEStream::StreamUnderflowCallback, this);

  int flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
  if (options && AESTREAM_FORCE_RESAMPLE)
    flags |= PA_STREAM_VARIABLE_RATE;

  if (pa_stream_connect_playback(m_Stream, NULL, NULL, (pa_stream_flags)flags, &m_ChVolume, NULL) < 0)
  {
    CLog::Log(LOGERROR, "PulseAudio: Failed to connect stream to output");
    pa_threaded_mainloop_unlock(m_MainLoop);
    Destroy();
    return /*false*/;
  }

  /* Wait until the stream is ready */
  do
  {
    pa_threaded_mainloop_wait(m_MainLoop);
    CLog::Log(LOGDEBUG, "PulseAudio: Stream %s", StreamStateToString(pa_stream_get_state(m_Stream)));
  }
  while (pa_stream_get_state(m_Stream) != PA_STREAM_READY && pa_stream_get_state(m_Stream) != PA_STREAM_FAILED);

  if (pa_stream_get_state(m_Stream) == PA_STREAM_FAILED)
  {
    CLog::Log(LOGERROR, "PulseAudio: Waited for the stream but it failed");
    pa_threaded_mainloop_unlock(m_MainLoop);
    Destroy();
    return /*false*/;
  }

  m_cacheSize = pa_stream_writable_size(m_Stream);

  pa_threaded_mainloop_unlock(m_MainLoop);

  m_Initialized = true;

  CLog::Log(LOGINFO, "PulseAEStream::Initialized");
  CLog::Log(LOGINFO, "  Sample Rate   : %d", m_sampleRate);
  CLog::Log(LOGINFO, "  Sample Format : %s", CAEUtil::DataFormatToStr(m_format));
  CLog::Log(LOGINFO, "  Channel Count : %d", m_channelLayout.Count());
  CLog::Log(LOGINFO, "  Channel Layout: %s", ((std::string)m_channelLayout).c_str());
  CLog::Log(LOGINFO, "  Frame Size    : %d", m_frameSize);
  CLog::Log(LOGINFO, "  Cache Size    : %d", m_cacheSize);

  Resume();

  return /*true*/;
}
Exemplo n.º 8
0
void
gst_pulse_cvolume_from_linear (pa_cvolume * v, unsigned channels,
    gdouble volume)
{
  pa_cvolume_set (v, channels, pa_sw_volume_from_linear (volume));
}
JNIEXPORT jint JNICALL
Java_org_jitsi_impl_neomedia_pulseaudio_PA_sw_1volume_1from_1linear
    (JNIEnv *env, jclass clazz, jdouble v)
{
    return pa_sw_volume_from_linear(v);
}
Exemplo n.º 10
0
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
    return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a)* pa_sw_volume_to_linear(b));
}
Exemplo n.º 11
0
int main(int argc, char *argv[]) {
    pa_volume_t v;
    pa_cvolume cv;
    float b;
    pa_channel_map map;
    pa_volume_t md = 0;
    unsigned mdn = 0;

    if (!getenv("MAKE_CHECK"))
        pa_log_set_level(PA_LOG_DEBUG);

    pa_log("Attenuation of sample 1 against 32767: %g dB", 20.0*log10(1.0/32767.0));
    pa_log("Smallest possible attenuation > 0 applied to 32767: %li", lrint(32767.0*pa_sw_volume_to_linear(1)));

    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {

        double dB = pa_sw_volume_to_dB(v);
        double f = pa_sw_volume_to_linear(v);

        pa_log_debug("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i",
               v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));
    }

    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 256) {
        char s[PA_CVOLUME_SNPRINT_MAX], t[PA_SW_CVOLUME_SNPRINT_DB_MAX];

        pa_cvolume_set(&cv, 2, v);

        pa_log_debug("Volume: %3i [%s] [%s]", v, pa_cvolume_snprint(s, sizeof(s), &cv), pa_sw_cvolume_snprint_dB(t, sizeof(t), &cv));
    }

    map.channels = cv.channels = 2;
    map.map[0] = PA_CHANNEL_POSITION_LEFT;
    map.map[1] = PA_CHANNEL_POSITION_RIGHT;

    for (cv.values[0] = PA_VOLUME_MUTED; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096)
        for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096) {
            char s[PA_CVOLUME_SNPRINT_MAX];

            pa_log_debug("Volume: [%s]; balance: %2.1f", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map));
        }

    for (cv.values[0] = PA_VOLUME_MUTED+4096; cv.values[0] <= PA_VOLUME_NORM*2; cv.values[0] += 4096)
        for (cv.values[1] = PA_VOLUME_MUTED; cv.values[1] <= PA_VOLUME_NORM*2; cv.values[1] += 4096)
            for (b = -1.0f; b <= 1.0f; b += 0.2f) {
                char s[PA_CVOLUME_SNPRINT_MAX];
                pa_cvolume r;
                float k;

                pa_log_debug("Before: volume: [%s]; balance: %2.1f", pa_cvolume_snprint(s, sizeof(s), &cv), pa_cvolume_get_balance(&cv, &map));

                r = cv;
                pa_cvolume_set_balance(&r, &map,b);

                k = pa_cvolume_get_balance(&r, &map);
                pa_log_debug("After: volume: [%s]; balance: %2.1f (intended: %2.1f) %s", pa_cvolume_snprint(s, sizeof(s), &r), k, b, k < b-.05 || k > b+.5 ? "MISMATCH" : "");
            }

    for (v = PA_VOLUME_MUTED; v <= PA_VOLUME_NORM*2; v += 51) {

        double l = pa_sw_volume_to_linear(v);
        pa_volume_t k = pa_sw_volume_from_linear(l);
        double db = pa_sw_volume_to_dB(v);
        pa_volume_t r = pa_sw_volume_from_dB(db);
        pa_volume_t w;

        pa_assert(k == v);
        pa_assert(r == v);

        for (w = PA_VOLUME_MUTED; w < PA_VOLUME_NORM*2; w += 37) {

            double t = pa_sw_volume_to_linear(w);
            double db2 = pa_sw_volume_to_dB(w);
            pa_volume_t p, p1, p2;
            double q, qq;

            p = pa_sw_volume_multiply(v, w);
            qq = db + db2;
            p2 = pa_sw_volume_from_dB(qq);
            q = l*t;
            p1 = pa_sw_volume_from_linear(q);

            if (p2 > p && p2 - p > md)
                md = p2 - p;
            if (p2 < p && p - p2 > md)
                md = p - p2;
            if (p1 > p && p1 - p > md)
                md = p1 - p;
            if (p1 < p && p - p1 > md)
                md = p - p1;

            if (p1 != p || p2 != p)
                mdn++;
        }
    }

    pa_log("max deviation: %lu n=%lu", (unsigned long) md, (unsigned long) mdn);

    pa_assert(md <= 1);
    pa_assert(mdn <= 251);

    return 0;
}