2

我正在训练用耳朵阅读摩尔斯电码;)

为了训练自己,我编写了一个小红宝石脚本来使用命令行生成声音文件sox(见下文)。dit它基本上只需要s、dahs 和多个空格(在dits 和s 之间,字母之间和单词之间)的预制声音文件dah并将它们粘合在一起。它可以工作,但是目标文件越大,速度就越慢。

有没有更聪明的方法可以用 ruby​​ 将声音生成到 wav 文件中?


#!/usr/bin/ruby

wordlength = 5
blocklength = 12
testlength = 5
alphabet = [ "G", "A", "S", "5", "D", "0", "R", "/", "2", "L", "9", "T", "V", "I", "O", "Q", "C", "4", "F", "X", "E", "N", "U" ]
playstring = ""
block = ""
page = ""

MORSE = {
        "!" => "---.", "\"" => ".-..-.", "$" => "...-..-", "'" => ".----.",
        "(" => "-.--.", ")" => "-.--.-", "+" => ".-.-.", "," => "--..--",
        "-" => "-....-", "." => ".-.-.-", "/" => "-..-.", "0" => "-----",
        "1" => ".----", "2" => "..---", "3" => "...--", "4" => "....-", "5" => ".....",
        "6" => "-....", "7" => "--...", "8" => "---..", "9" => "----.", ":" => "---...",
        ";" => "-.-.-.", "=" => "-...-", "?" => "..--..", "@" => ".--.-.", "A" => ".-",
        "B" => "-...", "C" => "-.-.", "D" => "-..", "E" => ".", "F" => "..-.",
        "G" => "--.", "H" => "....", "I" => "..", "J" => ".---", "K" => "-.-",
        "L" => ".-..", "M" => "--", "N" => "-.", "O" => "---", "P" => ".--.",
        "Q" => "--.-", "R" => ".-.", "S" => "...", "T" => "-", "U" => "..-",
        "V" => "...-", "W" => ".--", "X" => "-..-", "Y" => "-.--", "Z" => "--..",
        "[" => "-.--.", "]" => "-.--.-", "_" => "..--.-", 
        "ka" => "-.-.-.",
}

startblock = "dit.wav ditspace.wav dit.wav ditspace.wav dit.wav ditspace.wav dah.wav wordspace.wav dit.wav ditspace.wav dit.wav ditspace.wav dit.wav ditspace.wav dah.wav wordspace.wav dit.wav ditspace.wav dit.wav ditspace.wav dit.wav ditspace.wav dah.wav wordspace.wav dah.wav ditspace.wav dit.wav ditspace.wav dah.wav ditspace.wav dit.wav ditspace.wav dah.wav wordspace.wav wordspace.wav wordspace.wav "
endblock = "dit.wav ditspace.wav dah.wav ditspace.wav dit.wav ditspace.wav dah.wav ditspace.wav dit.wav blockspace.wav "

playstring << "uebungsanfang.wav wordspace.wav "
system ('/opt/local/bin/sox ' + playstring.to_s + ' tmp.wav 2>/dev/null')
system ('mv tmp.wav tmp2.wav')
playstring = ""

testlength.times do |line|
    printf line.to_s + " "
    playstring << "gruppe" + (line+1).to_s + ".wav wordspace.wav "
    playstring << startblock
    system ('/opt/local/bin/sox tmp2.wav ' + playstring.to_s + ' tmp.wav 2>/dev/null')
    system ('mv tmp.wav tmp2.wav')
    playstring = ""
    blocklength.times do |count|
        word = alphabet.sample.to_s + alphabet.sample.to_s + alphabet.sample.to_s + alphabet.sample.to_s + alphabet.sample.to_s
        word.each_char do |char|
            MORSE[char].each_char do |dahdit|
                case dahdit
                    when '.' then playstring << "dit.wav "
                    when '-' then playstring << "dah.wav "
                end
                playstring << "ditspace.wav "
            end
            playstring << "letterspace.wav "
            system ('/opt/local/bin/sox tmp2.wav ' + playstring.to_s + ' tmp.wav 2>/dev/null')
            system ('mv tmp.wav tmp2.wav')
            playstring = ""
        end
        playstring << "wordspace.wav "
        block << word.to_s + " "
    end
    playstring << endblock
    playstring << "blockspace.wav "
    system ('/opt/local/bin/sox tmp2.wav ' + playstring.to_s + ' tmp.wav')  #2>/dev/null
    system ('mv tmp.wav tmp2.wav')
    playstring = ""
    page << "%02d" %(line+1).to_s + ": VVV <ak> " + block + "+" + "\n"
    block = ""
end
playstring << "uebungsende.wav"
system ('/opt/local/bin/sox tmp2.wav ' + playstring.to_s + ' tmp.wav 2>/dev/null') #  &
system ('rm tmp2.wav')
system ('mv tmp.wav cw.wav')
system ('lame --cbr -b 128 cw.wav cw.mp3')
system ('rm cw.wav')
puts
puts page

声音文件是使用 sox 预先生成的:

sox -e floating-point -r 22500 -n -t wav - synth 0.3 sin 0 > letterspace.wav

包含Übungsende等(测试开始,测试结束,第一组,第二组,...)的文件是使用 MAC OS X 命令生成的say

say -v Steffi --file-format=WAVE --data-format=LEF32@22500 -o uebungsanfang.wav "Anfang der Übung."

我已经在这里上传了文件(直到“Gruppe 5”,即“group 5”): https://docs.google.com/open?id=0B4QwMfBGRCjVbE5iZHpHMHBKT3c

4

1 回答 1

2

我不知道 ruby​​,所以我不完全确定我知道你在做什么,但似乎你正在生成代表点、破折号、空格等的音频文件,然后使用 sox 连接这些文件中的原始数据到一个新文件,然后使用 lame 将其转换为 mp3。

总而言之,这是非常低效的,主要是因为您使用可以动态生成的原始文件做了很多事情。也就是说,可能不值得以最有效的方式重写——毕竟,执行所有文件 IO 会使您的代码变得简单。所以我会重写代码,使文件 IO 尽可能快。在这种情况下,必须一遍又一遍地打开和解析 WAV 文件,尤其是 32 位浮点 WAV 文件,可能会减慢您的速度。对于你正在做的事情,你绝对不需要那个。我将从使用 16 位整数 WAV 文件开始。

要获得更高的速度,请尝试使用更简单的格式作为中间格式,例如au(如果足够好则使用 u-law,否则使用 16 位线性)。您也可以尝试“原始”文件,即“无头”文件——只需告诉 sox 并蹩脚采样率、位深度、字节顺序和要使用的样本数。然后你不需要使用 sox 来连接原始数据,你可以使用 "cat" unix 工具,它会更快一点。

于 2012-11-28T22:38:57.577 回答