| 元素 | 符號 | 時長單位 | 說明 |
| 點 | . | 1 單位 | 基本單位 |
| 划 | - | 3 單位 | 3 個點時長 |
| 元素間間隙 | (點/划之間) | 1 單位 | 同一字元內 |
| 字元間間隙 | (字母之間) | 3 單位 | 3 個點時長 |
| 單詞間間隙 | (單詞之間) | 7 單位 | 7 個點時長 |
摩斯密碼對照表(標準國際電信聯盟 ITU-R M.1677)
MORSE_CODE = {
'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': '--..',
'0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-',
'5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.',
'.': '.-.-.-', ',': '--..--', '?': '..--..', "'": '.----.', '!': '-.-.--',
'/': '-..-.', '(': '-.--.', ')': '-.--.-', '&': '.-...', ':': '---...',
';': '-.-.-.', '=': '-...-', '+': '.-.-.', '-': '-....-', '_': '..--.-',
'"': '.-..-.', '$': '...-..-', '@': '.--.-.', ' ': '/'
}
完整實作程式碼
import pygame
import time
import sys
import os
# === 設定區 ===
ONE_UNIT = 0.15 # 基礎時間單位(秒),可調整速度
THREE_UNITS = 3 * ONE_UNIT
SEVEN_UNITS = 7 * ONE_UNIT
SOUND_DIR = "morse_sounds" # 音效檔案目錄
FREQUENCY = 800 # 蜂鳴器頻率 (Hz)
MORSE_CODE = {
'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': '--..', '0': '-----', '1': '.----', '2': '..---',
'3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...',
'8': '---..', '9': '----.', '.': '.-.-.-', ',': '--..--', '?': '..--..',
"'": '.----.', '!': '-.-.--', '/': '-..-.', '(': '-.--.', ')': '-.--.-',
'&': '.-...', ':': '---...', ';': '-.-.-.', '=': '-...-', '+': '.-.-.',
'-': '-....-', '_': '..--.-', '"': '.-..-.', '$': '...-..-', '@': '.--.-.',
' ': '/'
}
def verify_message(message):
"""驗證訊息只包含支援字元"""
valid_chars = set(MORSE_CODE.keys())
for char in message.upper():
if char not in valid_chars:
raise ValueError(f"不支援的字元: '{char}' (ASCII: {ord(char)})")
def play_sound(duration):
"""播放指定時長的蜂鳴聲(使用 pygame 生成正弦波)"""
# 動態生成音效避免需外部檔案
sample_rate = 44100
n_samples = int(sample_rate * duration)
buf = bytearray()
for i in range(n_samples):
t = i / sample_rate
# 正弦波
val = int(32767 * 0.5 * (1 + __import__('math').sin(2 * __import__('math').pi * FREQUENCY * t)))
buf.extend(val.to_bytes(2, 'little', signed=True))
sound = pygame.mixer.Sound(buffer=bytes(buf))
sound.play()
time.sleep(duration)
def play_morse_element(element):
"""播放單一點/划"""
if element == '.':
play_sound(ONE_UNIT)
elif element == '-':
play_sound(THREE_UNITS)
# 元素間間隙
time.sleep(ONE_UNIT)
def encode_to_morse(message):
"""編碼訊息為摩斯密碼字串"""
morse_parts = []
for char in message.upper():
if char == ' ':
morse_parts.append('/')
else:
morse_parts.append(MORSE_CODE.get(char, '?'))
return ' '.join(morse_parts)
def play_morse_message(message):
"""播放完整摩斯密碼訊息"""
verify_message(message)
print(f"原文: {message}")
morse = encode_to_morse(message)
print(f"摩斯: {morse}")
words = message.upper().split(' ')
for wi, word in enumerate(words):
for ci, char in enumerate(word):
code = MORSE_CODE[char]
print(f" {char}: {code}")
for element in code:
play_morse_element(element)
# 字元間間隙 (已在 play_morse_element 結尾包含 1 unit)
time.sleep(TWO_UNITS := 2 * ONE_UNIT) # 額外 2 unit = 總共 3 unit
# 單詞間間隙 (最後一個字元不需額外)
if wi < len(words) - 1:
time.sleep(SEVEN_UNITS - THREE_UNITS) # 已有 3 unit,補足 7 unit
def main():
print("=== 摩斯密碼翻譯器 ===")
print("支援字元: A-Z, 0-9, 空格, . , ? ' ! / ( ) & : ; = + - _ \" $ @")
print("輸入 'quit' 結束\n")
# 初始化 pygame mixer
pygame.mixer.init(frequency=44100, size=-16, channels=1, buffer=512)
try:
while True:
try:
message = input("請輸入訊息: ").strip()
if message.lower() in ('quit', 'exit', 'q'):
break
if not message:
continue
play_morse_message(message)
print("播放完成\n")
except ValueError as e:
print(f"錯誤: {e}\n")
except KeyboardInterrupt:
print("\n中斷播放")
break
finally:
pygame.mixer.quit()
if __name__ == "__main__":
main()
關鍵技術細節解析
1. 動態生成正弦波音效(無需外部檔案)
import pygame
import math
def generate_tone(frequency=800, duration=0.1, volume=0.5):
sample_rate = 44100
n_samples = int(sample_rate * duration)
buf = bytearray()
for i in range(n_samples):
t = i / sample_rate
# 正弦波:y = A * sin(2πft)
val = int(32767 * volume * math.sin(2 * math.pi * frequency * t))
buf.extend(val.to_bytes(2, 'little', signed=True))
return pygame.mixer.Sound(buffer=bytes(buf))
# 使用
tone = generate_tone(800, 0.3)
tone.play()
2. 精確時序控制
# 摩斯標準時序(以 1 unit 為基準)
DOT = 1
DASH = 3
INTRA_CHAR = 1 # 點/划之間
INTER_CHAR = 3 # 字元之間
INTER_WORD = 7 # 單詞之間
# 實作策略:每個元素播放後 sleep 1 unit
# 字元結束額外 sleep 2 unit (總共 3)
# 單詞結束額外 sleep 4 unit (總共 7)
3. 錯誤處理與驗證
def verify_message(message):
valid = set(MORSE_CODE.keys())
invalid = [c for c in message.upper() if c not in valid]
if invalid:
raise ValueError(f"不支援字元: {set(invalid)}")
進階擴展功能
1. 解碼功能(摩斯 → 文字)
# 反向查找表
MORSE_TO_CHAR = {v: k for k, v in MORSE_CODE.items()}
def decode_morse(morse_str):
"""解碼摩斯密碼字串(元素以空格分隔,字元以 / 分隔)"""
words = morse_str.strip().split(' / ')
result = []
for word in words:
chars = word.split()
decoded = ''.join(MORSE_TO_CHAR.get(c, '?') for c in chars)
result.append(decoded)
return ' '.join(result)
print(decode_morse(".... . .-.. .-.. --- / .-- --- .-. .-.. -.."))
# HELLO WORLD
2. GUI 介面
import tkinter as tk
from tkinter import ttk, scrolledtext
class MorseGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("摩斯密碼翻譯器")
# 輸入區
ttk.Label(self.root, text="輸入文字:").pack()
self.input_text = scrolledtext.ScrolledText(self.root, height=5)
self.input_text.pack(fill=tk.X, padx=5, pady=5)
# 輸出區
ttk.Label(self.root, text="摩斯密碼:").pack()
self.output_text = scrolledtext.ScrolledText(self.root, height=5)
self.output_text.pack(fill=tk.X, padx=5, pady=5)
# 按鈕
ttk.Button(self.root, text="編碼並播放", command=self.encode_play).pack(pady=5)
ttk.Button(self.root, text="解碼", command=self.decode).pack(pady=5)
def encode_play(self):
text = self.input_text.get("1.0", tk.END).strip()
if text:
morse = encode_to_morse(text)
self.output_text.delete("1.0", tk.END)
self.output_text.insert("1.0", morse)
play_morse_message(text)
def decode(self):
morse = self.output_text.get("1.0", tk.END).strip()
if morse:
text = decode_morse(morse)
self.input_text.delete("1.0", tk.END)
self.input_text.insert("1.0", text)
def run(self):
self.root.mainloop()
3. 檔案輸出(WAV 音檔)
import wave
import struct
def save_morse_wav(message, filename="morse.wav"):
"""將摩斯密碼存為 WAV 檔案"""
sample_rate = 44100
morse = encode_to_morse(message)
with wave.open(filename, 'wb') as wav:
wav.setnchannels(1)
wav.setsampwidth(2)
wav.setframerate(sample_rate)
for char in message.upper():
if char == ' ':
# 單詞間隙
write_silence(wav, SEVEN_UNITS)
continue
code = MORSE_CODE.get(char, '')
for element in code:
if element == '.':
write_tone(wav, ONE_UNIT)
elif element == '-':
write_tone(wav, THREE_UNITS)
write_silence(wav, ONE_UNIT) # 元素間
write_silence(wav, TWO_UNITS) # 字元間補足
def write_tone(wav, duration):
# ... 寫入正弦波資料
pass
def write_silence(wav, duration):
# ... 寫入靜音資料
pass
安裝與執行
# 安裝依賴
pip install pygame
# 執行
python morse_translator.py
# 或直接編碼不播放
python -c "from morse_translator import encode_to_morse; print(encode_to_morse('SOS'))"
# ... --- ...
總結
Python 實作摩斯密碼翻譯器涵蓋:標準編碼表、精確時序控制、動態音效生成、錯誤驗證、解碼反向查找、GUI/WAV 擴展。關鍵技術點:pygame.mixer.Sound(buffer=...) 動態音效、time.sleep() 微秒級時序、dict 雙向映射。此專案適合學習聲音合成、時序控制、字串處理,也可作為無線電通訊教學輔助工具。
- 上一篇文章: Python 定時檢查進程狀態並自動重啟:監控腳本實作指南
- 下一篇文章: Python PyGame 播放聲音完整指南:基礎播放、音效管理、進階控制
Copyright ©
程式碼之家 All Rights Reserved