Dear Frank,
is it possible to add a proper "mpd script" which works as follows:
MPD -> pipe output -> MPD script -> Receiver
At the moment, I am using the pipe output of mpd to pipe the raw audio stream to a bash script called "pipehrt" (see mpd.conf):
audio_output { type "pipe" name "pipehrt" command "pipehrt" }
This script "pipehrt" (in analogy to your "play_writecatloop") now reads the raw audio stream from stdin for passing on this stream to a pipe cascaded with writeloop, catloop and finally playhrt command.
#!/bin/bash ######################################################################### ## frankl (C) 2015 play_writecatloop ## ## See README or http://frank_l.bitbucket.org/stereoutils/player.html ## for explanations. ######################################################################### CARD="hw:0,0" EXTRABYTESPLAY=397 VERBOSE="" #trap "trap - SIGTERM && kill -- -$$ " SIGINT SIGTERM EXIT #rm -f /dev/shm/bl{1,2,3} /dev/shm/sem.bl{1,2,3}* input_file="${1:-/dev/stdin}" cat "$input_file" | \ writeloop --block-size=1024 --file-size=4096 --shared /bl1 /bl2 /bl3 & # maybe the start of the background command takes a little time sleep 0.1 catloop --block-size=1024 --shared /bl1 /bl2 /bl3 | \ chrt -f 99 playhrt \ --stdin \ --device=${CARD} \ --sample-rate=44100 \ --sample-format=S16_LE \ --loops-per-second=1000 \ --mmap \ --non-blocking-write \ ${VERBOSE} \ --extra-bytes-per-second=${EXTRABYTESPLAY} \ --hw-buffer=16384
I am really no bash expert, but this approach works. The question is: is it really good script concerning audio quality and overall system overhead? Maybe you could help with this script and add it to your script examples. I am pretty sure that I am not the only person using mpd.
Thank you very much for your help and thanks for these great programs!
Best wishes, Martin
PS: writing the hole pipe sequence into the "command-field" of the pipe output in mpd.conf does not work (maybe because of the writeloop... & catloop... sequence)!
Comments (7)
-
repo owner -
repo owner - changed status to open
-
I tried the command mpd pipe with parameter substitution format in pipe with a modification of the code MPD. It worked, but after a while there is a failure of the audio stream and the sound disappears.
command "sox -traw -r$isr -c2 -esi -b$ifor - -traw -efloat -b64 - | volrace -t /tmp/volume | sox -traw -efloat -b64 -c2 -r$isr - -traw -esi -b32 - | chrt -f 80 aplay -fS32_LE -r$isr -c2 -Dplughw:0,0 --disable-resample"
MPD does resampling. $isr - input samplerate after resampling, $ifor - input format after resampling. Parameters are substituted dynamically. MPD writes volume to the file /tmp/volume in range 0..1.
Thanks, I'll try and your option.
I have a question: should be used volrace only for volume control? or Squeezelite volume function for one channel does the same?
s32_t gain(s32_t gain, s32_t sample) { s64_t res = (s64_t)gain * (s64_t)sample; if (res > MAX_SCALESAMPLE) res = MAX_SCALESAMPLE; if (res < MIN_SCALESAMPLE) res = MIN_SCALESAMPLE; return (s32_t) (res >> 16); }
gain - volume range 0..65536, sample -32768 ... 32768, s64_t - integer 64bit, s32_t - integer 32bit
-
repo owner I have a question: should be used volrace only for volume control? or Squeezelite volume function for one channel does the same?
If you only want volume control and no RACE functionality you can simplify your pipe to not using 'volrace'. A gain function as you show above should be fine instead of volrace.
BTW: which version of mpd are you talking about in your example? I cannot find anything about parameter substitution in the script for the pipe output in the mpd documentation. Can you post a link to the version of mpd you are using?
-
I use custom MPD lastest version 0.18, 0.19 with little mod. Before the opening of the pipe occurs parameter substitution. PipeOutputPlugin.cxx
ReplaceString(pd->cmd,"$ifor",ifor); //format ReplaceString(pd->cmd,"$ich",ich); //channels ReplaceString(pd->cmd,"$isr",isample); //sample rate pd->fh = popen(pd->cmd.c_str(),"w");
-
I use your utils with Squeezelite little mod also, great improvement! Internal pipe with "popen" like mpd with occurs $rate substitution. Pipe is read via the parameter file. my pipefile pipe3:
writeloop --blocksize=4096 --file-size=32768 /tmp/b1 /tmp/b2 /tmp/b3 | catloop --blocksize=4096 /tmp/b1 /tmp/b2 /tmp/b3 | chrt -f 80 playhrt --stdin --device=plughw:0,0 --sample-rate=$rate --sample-format=S32_LE
Squeezelite runs (Max samplerate limited 192K):
squeezelite -o - -a 32 -b $buffer -n $sqname -r 192000 -j pipe3
-
repo owner - edited description
- changed status to closed
- Log in to comment
Dear Martin,
Thanks for your suggestion. I have not used mpd (I don't like that it wants to read the music files and only sends the raw audio data to a pipe - this way the sample rate and bit depth cannot be transfered to the receiving program).
Nevertheless, I can add an example script to the next release, if you can confirm that it works.
Two comments on the script you propose above:
(1) The part with 'input_file' allows to read input from stdin or from a file given as argument. But this doesn't sound very sensible to me, because it is unlikely that someone stored raw audio data in a file. Therefore, the script can be simplified to only read from stdin:
(2) Why did you comment out the two lines with 'trap' and 'rm'. Do they not work? I would leave them uncommented, they ensure a cleanup if the script is killed during operation.
Best regards, Frank