Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Bug 1027713 - Part 1 - Add a volume API in cubeb and use it instead o…
Browse files Browse the repository at this point in the history
…f doing our own soft gain. r=kinetik
  • Loading branch information
padenot committed Jul 24, 2014
1 parent eea162d commit b06a6b9
Show file tree
Hide file tree
Showing 17 changed files with 509 additions and 31 deletions.
10 changes: 4 additions & 6 deletions content/media/AudioStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ AudioStream::AudioStream()
, mLatencyRequest(HighLatency)
, mReadPoint(0)
, mDumpFile(nullptr)
, mVolume(1.0)
, mBytesPerFrame(0)
, mState(INITIALIZED)
, mNeedsStart(false)
Expand Down Expand Up @@ -751,9 +750,11 @@ AudioStream::Available()
void
AudioStream::SetVolume(double aVolume)
{
MonitorAutoLock mon(mMonitor);
NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
mVolume = aVolume;

if (cubeb_stream_set_volume(mCubebStream, aVolume * GetVolumeScale()) != CUBEB_OK) {
NS_WARNING("Could not change volume on cubeb stream.");
}
}

void
Expand Down Expand Up @@ -1099,9 +1100,6 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
} else {
servicedFrames = GetTimeStretched(output, aFrames, insertTime);
}
float scaled_volume = float(GetVolumeScale() * mVolume);

ScaleAudioSamples(output, aFrames * mOutChannels, scaled_volume);

NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");

Expand Down
3 changes: 0 additions & 3 deletions content/media/AudioStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,6 @@ class AudioStream MOZ_FINAL
// frames.
CircularByteBuffer mBuffer;

// Software volume level. Applied during the servicing of DataCallback().
double mVolume;

// Owning reference to a cubeb_stream. cubeb_stream_destroy is called by
// nsAutoRef's destructor.
nsAutoRef<cubeb_stream> mCubebStream;
Expand Down
2 changes: 2 additions & 0 deletions layout/media/symbols.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ cubeb_stream_init
cubeb_stream_start
cubeb_stream_stop
cubeb_stream_get_latency
cubeb_stream_set_volume
cubeb_stream_set_panning
th_comment_clear
th_comment_init
th_decode_alloc
Expand Down
24 changes: 24 additions & 0 deletions media/libcubeb/include/cubeb.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,30 @@ int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
@retval CUBEB_ERROR */
int cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency);

/**
* Set the volume for a stream.
* @param stream the stream for which to adjust the volume.
* @param volumes a float between 0.0 (muted) and 1.0 (maximum volumes)
* @return CUBEB_ERROR_INVALID_PARAMETER if volume is outside [0.0; 1.0]
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is an invalid pointer
* @return CUBEB_OK otherwise
*/
int cubeb_stream_set_volume(cubeb_stream * stream, float volume);

/**
* If the stream is stereo, set the left/right panning. If the stream is mono,
* this has no effect.
* @param stream the stream for which to change the panning
* @param panning a number from -1.0 to 1.0. -1.0 means that the stream is fully
* mixed in the left channel, 1.0 means the stream is fully mixed in the right
* channel. 0.0 is equal power in the right and left channel (default).
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is outside
* the [-1.0; 1.0] range.
* @return CUBEB_ERROR if this stream is not mono nor stereo.
* @return CUBEB_OK otherwise.
*/
int cubeb_stream_set_panning(cubeb_stream * stream, float panning);

#if defined(__cplusplus)
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions media/libcubeb/src/cubeb-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct cubeb_ops {
int (* stream_stop)(cubeb_stream * stream);
int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
int (* stream_set_volume)(cubeb_stream * stream, float volumes);
int (* stream_set_panning)(cubeb_stream * stream, float panning);
};

#endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
19 changes: 19 additions & 0 deletions media/libcubeb/src/cubeb.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,22 @@ cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency)

return stream->context->ops->stream_get_latency(stream, latency);
}

int
cubeb_stream_set_volume(cubeb_stream * stream, float volume)
{
if (!stream || volume > 1.0 || volume < 0.0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}

return stream->context->ops->stream_set_volume(stream, volume);
}

int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
{
if (!stream || panning < -1.0 || panning > 1.0) {
return CUBEB_ERROR_INVALID_PARAMETER;
}

return stream->context->ops->stream_set_panning(stream, panning);
}
39 changes: 37 additions & 2 deletions media/libcubeb/src/cubeb_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ struct cubeb_stream {
PulseAudio where streams would stop requesting new data despite still
being logically active and playing. */
struct timeval last_activity;
float volume;
};

static int
Expand Down Expand Up @@ -313,7 +314,20 @@ alsa_refill_stream(cubeb_stream * stm)
return ERROR;
}
if (got > 0) {
snd_pcm_sframes_t wrote = snd_pcm_writei(stm->pcm, p, got);
snd_pcm_sframes_t wrote;

if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE) {
float * b = (float *) p;
for (uint32_t i = 0; i < got * stm->params.channels; i++) {
b[i] *= stm->volume;
}
} else {
short * b = (short *) p;
for (uint32_t i = 0; i < got * stm->params.channels; i++) {
b[i] *= stm->volume;
}
}
wrote = snd_pcm_writei(stm->pcm, p, got);
if (wrote == -EPIPE) {
snd_pcm_recover(stm->pcm, wrote, 1);
wrote = snd_pcm_writei(stm->pcm, p, got);
Expand Down Expand Up @@ -813,6 +827,7 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
stm->user_ptr = user_ptr;
stm->params = stream_params;
stm->state = INACTIVE;
stm->volume = 1.0;

r = pthread_mutex_init(&stm->mutex, NULL);
assert(r == 0);
Expand Down Expand Up @@ -1083,6 +1098,24 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
return CUBEB_OK;
}

int
alsa_stream_set_volume(cubeb_stream * stm, float volume)
{
/* setting the volume using an API call does not seem very stable/supported */
pthread_mutex_lock(&stm->mutex);
stm->volume = volume;
pthread_mutex_unlock(&stm->mutex);

return CUBEB_OK;
}

int
alsa_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(0 && "not implemented");
return CUBEB_OK;
}

static struct cubeb_ops const alsa_ops = {
.init = alsa_init,
.get_backend_id = alsa_get_backend_id,
Expand All @@ -1095,5 +1128,7 @@ static struct cubeb_ops const alsa_ops = {
.stream_start = alsa_stream_start,
.stream_stop = alsa_stream_stop,
.stream_get_position = alsa_stream_get_position,
.stream_get_latency = alsa_stream_get_latency
.stream_get_latency = alsa_stream_get_latency,
.stream_set_volume = alsa_stream_set_volume,
.stream_set_panning = alsa_stream_set_panning
};
28 changes: 26 additions & 2 deletions media/libcubeb/src/cubeb_audiotrack.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct AudioTrack {
/* static */ int (*get_output_latency)(uint32_t* latency, int stream);
/* static */ int (*get_output_samplingrate)(int* samplerate, int stream);
status_t (*set_marker_position)(void* instance, unsigned int);

status_t (*set_volume)(void* instance, float left, float right);
};

struct cubeb {
Expand Down Expand Up @@ -251,6 +251,7 @@ audiotrack_init(cubeb ** context, char const * context_name)
DLSYM_DLERROR("_ZN7android10AudioTrack5pauseEv", ctx->klass.pause, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack11getPositionEPj", ctx->klass.get_position, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack17setMarkerPositionEj", ctx->klass.set_marker_position, ctx->library);
DLSYM_DLERROR("_ZN7android10AudioTrack9setVolumeEff", ctx->klass.set_volume, ctx->library);

/* check that we have a combination of symbol that makes sense */
c = &ctx->klass;
Expand Down Expand Up @@ -468,6 +469,27 @@ audiotrack_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
return 0;
}

int
audiotrack_stream_set_volume(cubeb_stream * stream, float volume)
{
status_t status;

status = stream->context->klass.set_volume(stream->instance, volume, volume);

if (status) {
return CUBEB_ERROR;
}

return CUBEB_OK;
}

int
audiotrack_stream_set_panning(cubeb_stream * stream, float panning)
{
assert(false && "not implemented.");
return CUBEB_OK;
}

static struct cubeb_ops const audiotrack_ops = {
.init = audiotrack_init,
.get_backend_id = audiotrack_get_backend_id,
Expand All @@ -480,5 +502,7 @@ static struct cubeb_ops const audiotrack_ops = {
.stream_start = audiotrack_stream_start,
.stream_stop = audiotrack_stream_stop,
.stream_get_position = audiotrack_stream_get_position,
.stream_get_latency = audiotrack_stream_get_latency
.stream_get_latency = audiotrack_stream_get_latency,
.stream_set_volume = audiotrack_stream_set_volume,
.stream_set_panning = audiotrack_stream_set_panning
};
41 changes: 40 additions & 1 deletion media/libcubeb/src/cubeb_audiounit.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "cubeb/cubeb.h"
#include "cubeb-internal.h"
#include "cubeb_panner.h"

#if !defined(kCFCoreFoundationVersionNumber10_7)
/* From CoreFoundation CFBase.h */
Expand Down Expand Up @@ -46,6 +47,7 @@ struct cubeb_stream {
int draining;
uint64_t current_latency_frames;
uint64_t hw_latency_frames;
float panning;
};

static int64_t
Expand All @@ -70,6 +72,7 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
unsigned char * buf;
long got;
OSStatus r;
float panning;

assert(bufs->mNumberBuffers == 1);
buf = bufs->mBuffers[0].mData;
Expand All @@ -79,6 +82,7 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
pthread_mutex_lock(&stm->mutex);

stm->current_latency_frames = audiotimestamp_to_latency(tstamp, stm);
panning = stm->panning;

if (stm->draining || stm->shutdown) {
pthread_mutex_unlock(&stm->mutex);
Expand Down Expand Up @@ -113,6 +117,10 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
stm->frames_queued += got;
pthread_mutex_unlock(&stm->mutex);

if (stm->sample_spec.mChannelsPerFrame == 2) {
cubeb_pan_stereo_buffer_float((float*)buf, got, panning);
}

return noErr;
}

Expand Down Expand Up @@ -617,6 +625,35 @@ audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
return CUBEB_OK;
}

int audiounit_stream_set_volume(cubeb_stream * stm, float volume)
{
AudioDeviceID id;
OSStatus r;

r = AudioUnitSetParameter(stm->unit,
kHALOutputParam_Volume,
kAudioUnitScope_Global,
0, volume, 0);

if (r != noErr) {
return CUBEB_ERROR;
}
return CUBEB_OK;
}

int audiounit_stream_set_panning(cubeb_stream * stm, float panning)
{
if (stm->sample_spec.mChannelsPerFrame > 2) {
return CUBEB_ERROR_INVALID_PARAMETER;
}

pthread_mutex_lock(&stm->mutex);
stm->panning = panning;
pthread_mutex_unlock(&stm->mutex);

return CUBEB_OK;
}

static struct cubeb_ops const audiounit_ops = {
.init = audiounit_init,
.get_backend_id = audiounit_get_backend_id,
Expand All @@ -629,5 +666,7 @@ static struct cubeb_ops const audiounit_ops = {
.stream_start = audiounit_stream_start,
.stream_stop = audiounit_stream_stop,
.stream_get_position = audiounit_stream_get_position,
.stream_get_latency = audiounit_stream_get_latency
.stream_get_latency = audiounit_stream_get_latency,
.stream_set_volume = audiounit_stream_set_volume,
.stream_set_panning = audiounit_stream_set_panning
};
Loading

0 comments on commit b06a6b9

Please sign in to comment.