playaudio
は壊れてます!
playsound
(バージョン 3.6.2)のデフォルトの実装を読む価値があります。
function playaudio (name, ext)
if (nargin < 1 || nargin > 2)
print_usage ();
endif
if (nargin == 1 && isnumeric (name))
## play a vector
if (! isvector (name))
error ("playaudio: X must be a vector");
endif
X = name(:) + 127;
unwind_protect
file = tmpnam ();
fid = fopen (file, "wb");
fwrite (fid, X, "uchar");
fclose (fid);
[status, out] = system (sprintf ('cat "%s" > /dev/dsp', file));
if (status != 0)
system (sprintf ("paplay --raw \"%s\"", file))
endif
unwind_protect_cleanup
unlink (file);
end_unwind_protect
elseif (nargin >= 1 && ischar (name))
## play a file
if (nargin == 1)
name = [name ".lin"];
elseif (nargin == 2)
name = [name "." ext];
endif
if (any (strcmp (ext, {"lin", "raw"})))
[status, out] = system (sprintf ('cat "%s" > /dev/dsp', name));
if (status != 0)
system (sprintf ('paplay --raw "%s"', name))
endif
elseif (any (strcmp (ext, {"mu", "au" "snd", "ul"})))
[status, out] = system (sprintf ('cat "%s" > /dev/audio', name));
if (status != 0)
system (sprintf ('paplay "%s"', name))
endif
else
error ("playaudio: unsupported extension '%s'", ext);
endif
else
print_usage ();
endif
endfunction
注意すべき点がいくつかあります。
- /dev/dsp への直接書き込みは、最新の Linux ディストリビューションでは常に失敗するため、コマンドを実行するたびに (
cat > /dev/dsp
行で) エラーが発生します。
paplay
コマンドラインの pulseaudio プレーヤーであるを使用するようにハードコードされています。
- デフォルトは(おそらくタイプミスです。署名付きの16ビットビッグエンディアンを意味していると思います)、署名なしの8ビットを書き込むため、
paplay
呼び出しは決して機能しません!paplay
s16ne
s16be
playaudio
- を使って呼び出します
system()
。常に悪い考えです。
- オーディオをストリーミングするのではなく、ファイルに書き出します。大きなファイルで問題が発生する可能性があります。
- matlab とは異なり、浮動小数点オーディオを処理しません。実際には 8 ビット オーディオのみをサポートしています。それが wavread によって返された結果なので、ちょっとばかげています!
- matlab とは異なり、1 つのサンプル レート (44100 Hz) のみをサポートします。
この関数は非常にハックで、安全でなく、信頼性がありません。それが何らかの方法で Octave の他の場所でのコード品質を表しているとしたら...まあ、それは心配です。portaudio を使用して、Octave で適切な機能として再実装する必要があります。
少し良いバージョン
私には、オクターブで多くのハッキングを行う時間も動機もありません。そのため、当面は、代わりに次の少し優れた関数を使用することをお勧めします。
function playsound(wav, samplerate)
# Play a single-channel wave at a certain sample rate (defaults to 44100 Hz).
# Input can be integer, in which case it is assumed to be signed 16-bit, or
# float, in which case it is in the range -1:1.
if (nargin < 1 || nargin > 2)
print_usage();
endif
if (nargin < 2)
samplerate = 44100;
end
if (!isvector(wav))
error("playsound: X must be a vector");
endif
# Write it as a 16-bit signed, little endian (though the amaaazing docs don't say the endianness)
# If it is integers we assume it is 16 bit signed. Otherwise we assume in the range -1:1
if (isfloat(wav))
X = min(max(wav(:), -1), 1) * 32767; # Why matlab & octave do not have a clip() function... I do not know.
else
X = min(max(wav(:), -32767), 32767) + 32767;
endif
unwind_protect
file = tmpnam ();
fid = fopen (file, "wb");
fwrite (fid, X, "int16");
fclose (fid);
# Making aplay (alsa) the default, because let's be honest: it is still way more reliable than
# the mess that is pulseaudio.
if (exist("/usr/bin/aplay") == 2)
system(sprintf("/usr/bin/aplay --format=S16_LE --channels=1 --rate=%d \"%s\"", samplerate, file))
elseif (exist("/usr/bin/paplay") == 2)
system(sprintf("/usr/bin/paplay --format=s16le --channels=1 --rate=%d --raw \"%s\"", samplerate, file))
endif
unwind_protect_cleanup
unlink (file);
end_unwind_protect
endfunction
これはまだ非常にハックな関数です。playaudio
しかし、少なくとも!よりも信頼性が少し高くなるはずです。の実装はsoundsc
、読者の演習として残しておきます。