aboutsummaryrefslogtreecommitdiffstats
path: root/src/audioOutput_shout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/audioOutput_shout.c')
-rw-r--r--src/audioOutput_shout.c88
1 files changed, 82 insertions, 6 deletions
diff --git a/src/audioOutput_shout.c b/src/audioOutput_shout.c
index fdf1937a4..628483d21 100644
--- a/src/audioOutput_shout.c
+++ b/src/audioOutput_shout.c
@@ -24,6 +24,7 @@
#include "conf.h"
#include "log.h"
#include "sig_handlers.h"
+#include "pcm_utils.h"
#include <stdlib.h>
#include <string.h>
@@ -54,6 +55,15 @@ typedef struct _ShoutData {
vorbis_comment vc;
int serialno;
+
+ float quality;
+ AudioFormat outAudioFormat;
+ AudioFormat inAudioFormat;
+
+ char * convBuffer;
+ long convBufferLen;
+ /* shoud we convert the audio to a different format? */
+ int audioFormatConvert;
} ShoutData;
static ShoutData * newShoutData() {
@@ -61,6 +71,8 @@ static ShoutData * newShoutData() {
ret->shoutConn = shout_new();
ret->serialno = rand();
+ ret->convBuffer = NULL;
+ ret->convBufferLen = 0;
return ret;
}
@@ -112,6 +124,16 @@ static int shout_initDriver(AudioOutput * audioOutput) {
exit(EXIT_FAILURE);
}
+ if(!getConf()[CONF_SHOUT_QUALITY]) {
+ ERROR("shout host defined but not shout quality\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(!getConf()[CONF_SHOUT_FORMAT]) {
+ ERROR("shout host defined but not shout format\n");
+ exit(EXIT_FAILURE);
+ }
+
host = getConf()[CONF_SHOUT_HOST];
passwd = getConf()[CONF_SHOUT_PASSWD];
user = getConf()[CONF_SHOUT_USER];
@@ -126,6 +148,20 @@ static int shout_initDriver(AudioOutput * audioOutput) {
exit(EXIT_FAILURE);
}
+ sd->quality = strtod(getConf()[CONF_SHOUT_QUALITY], &test);
+
+ if(*test != '\0' || sd->quality < 0.0 || sd->quality > 10.0) {
+ ERROR("shout quality \"%s\" is not a number in the range "
+ "0-10\n", getConf()[CONF_SHOUT_QUALITY]);
+ exit(EXIT_FAILURE);
+ }
+
+ if(0 != parseAudioConfig(&(sd->outAudioFormat),
+ getConf()[CONF_SHOUT_FORMAT]) )
+ {
+ exit(EXIT_FAILURE);
+ }
+
if(shout_set_host(sd->shoutConn, host) != SHOUTERR_SUCCESS ||
shout_set_port(sd->shoutConn, port) != SHOUTERR_SUCCESS ||
shout_set_password(sd->shoutConn, passwd) != SHOUTERR_SUCCESS ||
@@ -202,8 +238,8 @@ static int shout_openDevice(AudioOutput * audioOutput,
vorbis_info_init(&(sd->vi));
- if( 0 != vorbis_encode_init_vbr(&(sd->vi), audioFormat->channels,
- audioFormat->sampleRate, 0.5) )
+ if( 0 != vorbis_encode_init_vbr(&(sd->vi), sd->outAudioFormat.channels,
+ sd->outAudioFormat.sampleRate, sd->quality) )
{
ERROR("problem seting up vorbis encoder for shout\n");
vorbis_info_clear(&(sd->vi));
@@ -230,19 +266,59 @@ static int shout_openDevice(AudioOutput * audioOutput,
write_page(sd);
}
+ memcpy(&(sd->inAudioFormat), audioFormat, sizeof(AudioFormat));
+
+ if(0 == memcmp(&(sd->inAudioFormat), &(sd->outAudioFormat),
+ sizeof(AudioFormat)))
+ {
+ sd->audioFormatConvert = 0;
+ }
+ else sd->audioFormatConvert = 1;
+
return 0;
}
+static void shout_convertAudioFormat(ShoutData * sd, char ** chunkArgPtr,
+ int * sizeArgPtr)
+{
+ int size = pcm_sizeOfOutputBufferForAudioFormatConversion(
+ &(sd->inAudioFormat), *sizeArgPtr,
+ &(sd->outAudioFormat));
+
+ if(size > sd->convBufferLen) {
+ sd->convBuffer = realloc(sd->convBuffer, size);
+ sd->convBufferLen = size;
+ }
+
+ pcm_convertAudioFormat(&(sd->inAudioFormat), *chunkArgPtr, *sizeArgPtr,
+ &(sd->outAudioFormat), sd->convBuffer);
+
+ *sizeArgPtr = size;
+ *chunkArgPtr = sd->convBuffer;
+}
static int shout_play(AudioOutput * audioOutput, char * playChunk, int size) {
int i,j;
ShoutData * sd = (ShoutData *)audioOutput->data;
+ float ** vorbbuf;
+ int samples;
+ int bytes = sd->outAudioFormat.bits/8;
+
+ if(sd->audioFormatConvert) {
+ shout_convertAudioFormat(sd, &playChunk, &size);
+ }
- float **vorbbuf = vorbis_analysis_buffer(&(sd->vd), size/4);
+ samples = size/(bytes*sd->outAudioFormat.channels);
- for(i=0, j=0; i < size; i+=4, j++) {
- vorbbuf[0][j] = (*((mpd_sint16 *)(playChunk+i))) / 32768.0;
- vorbbuf[1][j] = (*((mpd_sint16 *)(playChunk+i+2))) / 32768.0;
+ /* this is for only 16-bit audio */
+
+ vorbbuf = vorbis_analysis_buffer(&(sd->vd), samples);
+
+ for(i=0; i<samples; i++) {
+ for(j=0; j<sd->outAudioFormat.channels; j++) {
+ vorbbuf[j][i] = (*((mpd_sint16 *)playChunk)) / 32768.0;
+ playChunk += bytes;
+ }
}
vorbis_analysis_wrote(&(sd->vd), size/4);