通过 play、aplay、/dev/sound 等管道传输 cdparanoia

通过 play、aplay、/dev/sound 等管道传输 cdparanoia

目前,我正在尝试使用 cdparanoia 直接从音频 CD 播放,而不创建任何临时文件。我可以通过以下方式实时播放 CD 的第一首曲目

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

但是我不想使用这种方法,因为它会产生临时文件,有时我的 /dev/shm 已满,而且我想要一个可以用一行写完的更优雅的解决方案。

我在 Linux 上使用 bash 尝试了两种解决方案。

首先:

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

什么也没做。第二个:

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

这只是发出随机的刮擦声,表明数据格式不正确。我怀疑它可能是 16 位而不是 8 位。

如果有人有解决方案,请告诉我。我正在寻找一行中没有临时文件的 POSIX Bash 解决方案。

答案1

我知道,这是一个很老的问题,但没人回答……

将 cdparanoia 的输出直接传输到音频输出接收器并不是很实用。第一个问题是任何类型的错误检测和纠正都不会实时完成,事实上,它需要尽可能长的时间才能获得正确的输出。即使没有检测到错误,重复的重叠读取也意​​味着它不太可能实时产生输出。最后,即使关闭了所有检测和纠正模式(PARANOIA_MODE_DISABLE),该库也会一次读取大量数据(超过 10 秒)以启用对该数据的多次传递。然后它会转储该数据并尝试再获取 10 秒,同时您的音频即使在最快的驱动器和 CPU 上也可能会暂停。

使用小缓存(1-2 秒)并禁用所有错误更正来运行 cdparanoia,您可以实时从 cdparanoia 中获取数据。-p 选项将生成 16 位原始 PCM 数据。16 位应该没问题。您可能需要使用 -r/R 指定字节序。我认为您不能再将原始音频直接传输到 /dev/sound,这已经是历史了,但根据您的声音驱动程序,也许它可以工作。传输到 play 是一个更好的主意,但 play 可以是任何东西,因此很难说您需要什么选项。aplay 与 alsa 配合使用很方便,但您需要告诉它原始数据是什么,例如:aplay -c 2 -f S16_LE -r 44100

答案2

对于任何在这里寻找答案的人:
我无法找到将cdparanoia输出到 stdout 的方法,但cd-readfromlibcdio-utils能够直接从 CD 输出。您可以使用此命令播放 CD:

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

这将读取<sectors>从 开始的扇区<start>,将它们限制为正确的比特率,并通过扬声器播放输出。我使用 0 和<start>40000 作为<sectors>测试,但您可以从 获得正确的值cdparanoia -Q
如果您想pv显示当前位置/长度,请添加--size <sectors*2352>到 的末尾pv -L 176400

编辑:这是我编写的 shell 脚本,可以从命令行播放 CD。您可以不输入任何参数(first -> last)、输入起始曲目(start -> last)、输入起始和结束曲目(start -> end),或者~输入随机播放(? -> ?)。

#!/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;

答案3

将 cdparanoia 直接连接到某些输出根本没有意义:cd 的想法偏执狂是对可能出现的不准确性保持警惕,并反复读取所有内容,如果 CD 驱动器出现抖动等情况。

如果您只想直接播放 CD 上的音轨,您可以使用例如 mplayer:

mplayer cdda://

相关内容