目前,我正在尝试使用 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-read
fromlibcdio-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://