piping cdparanoia through play, aplay, /dev/sound, etc

1

Currently I am trying to use cdparanoia to play from an audio cd directly without making any temporary files. I can play the first track of a cd realtime by doing

cdparanoia -e 1 /dev/shm/tmp.wav 2>/dev/null &
play /dev/shm/tmp.wav

however I don't want to use this method because it makes temporary files, sometimes my /dev/shm is full and because I want a more elegant solution which can be written in one line.

I tried two solutions on Linux using bash.

The first:

cdparanoia -e 1 - 2>/dev/null | play -

did nothing. The second:

cdparanoia -pe 1 - 2>/dev/null 1>/dev/sound

This just made random scratching sounds showing that the data is not formatted correctly. I suspect it may be 16bit instead of 8bit.

If anyone has a solution let me know. I am looking for a POSIX Bash solution in one line with no temporary files.

Sudo Bash

Posted 2012-06-23T16:50:08.903

Reputation: 93

Answers

1

For anyone looking for answers here:
I couldn't figure out a way to get cdparanoia to output to stdout, but cd-read from libcdio-utils is able to output straight from the CD. You can use this command to play the CD:

cd-read -m audio -s <start> -n <sectors> --no-hexdump | pv -L 176400 | aplay -c 2 -f S16_BE -r 44100

This will read <sectors> sectors starting at <start>, throttle them to the correct bitrate, and play the output through the speakers. I used 0 for <start> and 40000 for <sectors> as a test, but you can get the correct values from cdparanoia -Q.
If you want pv to show the current position/length, add --size <sectors*2352> to the end of pv -L 176400.

EDIT: Here's a shell script that I wrote that can play CD's from the command line. You can type no arguments (first -> last), the start track (start -> last), the start and end tracks (start -> end), or ~ for shuffle (? -> ?).

#!/bin/bash
CDINFO="$(cdparanoia -Q 2>&1 | grep -E "[0-9]+\. ")";
TRACKS=$(echo "$CDINFO" | wc -l);
if [ $# -lt 1 ]; then  START=1; else if [ $1 == '~' ]; then RAND=1; START=$(expr $RANDOM \% $TRACKS + 1); else START=$1; fi;$
if [ $# -lt 2 ]; then END=-1; else END=$2; fi;

while (true); do
    STARTBLOCK=$(echo "$CDINFO" | grep " $START\. " | awk '{print $4}');
    LENGTH=$(echo "$CDINFO" | grep " $START\. " | awk '{print $2}');
    echo "Playing track $START...";
    cd-read -m audio -s $STARTBLOCK -n $LENGTH --no-hexdump | pv -L 176400 --size $(expr $LENGTH \* 2352) | aplay -c 2 -f S1$
    if [ "$RAND" == "1" ]; then START=$(expr $RANDOM \% $TRACKS + 1); else START=$(( $START + 1 )); fi;
    if [ $END -ne -1 ]; then if [ $START -gt $END ]; then break; fi; fi;
    if [ $START -gt $TRACKS ]; then break; fi;
done;

JackMacWindows

Posted 2012-06-23T16:50:08.903

Reputation: 11

1

I know, very old question, but nobody answered ...

Piping cdparanoia output directly into an audio output sink is not very practical. The first problem is that any sort of error detection and correction will not be done in real time, in fact it will take as long as necessary to get the correct output. Even when there are no errors detected, the repeated overlapped reads mean that it is unlikely to produce output in real time. Lastly, even with all the detection and correction modes turned off (PARANOIA_MODE_DISABLE), the library reads massive chunks of data at a time (over 10 seconds worth) to enable multiple passes over that data. Then it dumps that and tries to get another 10 seconds, meanwhile your audio is likely to pause even on the fastest drive and CPU.

Running cdparanoia with a small cache (1-2 seconds) and with all error correction disabled, you can get data out of cdparanoia in real time. The -p option will produce 16 bit raw PCM data. 16 bit should be fine. You may need to specify the endianness using -r/R. I don't think you can just pipe raw audio into /dev/sound any more, that's from the history books, but depending on your sound drivers maybe it will work. Piping to play is a better idea, but play could be anything so hard to say what options you'd need. aplay is handy with alsa but you will need to tell it what the raw data is, something like: aplay -c 2 -f S16_LE -r 44100

Ian Nartowicz

Posted 2012-06-23T16:50:08.903

Reputation: 11

0

Piping cdparanoia directly to some output makes no sense at all: The idea of cdparanoia is to be paranoid about possible inaccuracies, and repeatedly read everything if the CD drive has jitter etc.

If you just want to play audio tracks on the CD directly, you can use e.g. mplayer:

mplayer cdda://

dirkt

Posted 2012-06-23T16:50:08.903

Reputation: 11 627