モールス符号を検出するための一般的な解決策が必要な場合は、それが波形としてどのように見えるかを確認する必要があります (インストールできる場合は、この質問への tom10 のリンクが役立ちます。そうでない場合は、 stdlib のモジュールを使用して、お気に入りのスプレッドシート プログラムで使用できるファイルをエクスポートします); 人間として、ドット、ダッシュ、スペースをどのように区別できるかを考えてみましょう。それをアルゴリズムに変換します(文字通りのバカでも従うことができる一連のステップ)。次に、そのアルゴリズムをコードに変換します。または、すでにこれを行っているライブラリを見つけることができるかもしれません。numpy
matplotlib
csv
dot.wav
ただし、特定のケースでは、dash.wav
より大きなファイルの内容の正確なコピーを検出するだけで済みます。(少なくとも、可逆圧縮を使用していないと仮定します。これは通常 .wav ファイルにはありません。) したがって、これは実際には単なる部分文字列検索です。
'dot'
文字列を検出する方法と'dash'
、 のような文字列内を考えてみてください'dash dash dash dash dash dot dash dot dot dot dot dot '
。このような単純な問題には、ばかげた力ずくのアルゴリズムを使用できますが、それで問題ありません。
def find(haystack, needle, start):
for i in range(start, len(haystack)):
if haystack[i:i+len(needle)] == needle:
return i
return len(haystack)
def decode_morse(morse):
i = 0
while i < len(morse):
next_dot = find(morse, 'dot', i)
next_dash = find(morse, 'dash', i)
if next_dot < next_dash:
if next_dot < len(morse):
yield '.'
i = next_dot
else:
if next_dash < len(morse):
yield '-'
i = next_dash
では、文字列ではなく数字のリストを検索している場合、これをどのように変更する必要があるでしょうか? かろうじて。文字列と同じように、リストをスライスしたり、2 つのリストを比較したりできます。
実際に遭遇する唯一の問題は、リスト全体を一度にメモリに保持するのではなく、一度に 20 フレームしか保持できないことです。dot
aがフレーム 19 で始まり、フレーム 20 で終わるとどうなりますか? ファイルがそれほど大きくない場合、これは簡単に解決できます。1 つの巨大なリストですべてのフレームをメモリに読み込み、全体を検索するだけです。ただし、それ以外の場合は、バッファリングを行う必要があります。
たとえば (エラー処理を無視してファイルの末尾を適切に処理し、簡単にするためにダッシュのみを処理します。もちろん、実際のコードではこれらの両方を適切に行う必要があります)。
buf = []
while True:
while len(buf) < 2*len(dash):
buf.extend(waveFile.readFrames(20))
next_dash = find(buf, dot)
if next_dash < len(buf):
yield '.'
buf = buf[next_dash:]
else:
buf = buf[-len(dash):]
バッファーには常に少なくとも 2 つのダッシュの長さがあることを確認しています。そして、最初のドットまたはダッシュ (見つかった場合) または完全なダッシュ (見つからない場合) の後の残りを常にバッファーに保持し、それに次のバッファーを追加します。それは実際にはやり過ぎです。よく考えて、2 つのバッファの間にあるダッシュを見逃さないようにするために必要なことを正確に考えてください。しかし、重要なのは、それを正しく理解している限り、ドットやダッシュを見逃すことはできないということです。