convert_raw.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import argparse
  2. import struct
  3. import sys
  4. # 一度に処理するチャンクサイズ
  5. CHUNK_SIZE = 8192
  6. def convert_s16_to_u16(input_path, output_path):
  7. """
  8. 符号付き16bitのRAWオーディオファイルを符号なし16bitに変換する。
  9. """
  10. print(f"変換を開始します: '{input_path}' -> '{output_path}'")
  11. try:
  12. with open(input_path, 'rb') as infile, open(output_path, 'wb') as outfile:
  13. while True:
  14. # ファイルからチャンクを読み込む
  15. s16_chunk = infile.read(CHUNK_SIZE)
  16. if not s16_chunk:
  17. break # ファイルの終端に達したらループを抜ける
  18. # チャンク内のサンプル数を計算 (1サンプル = 2バイト)
  19. num_samples = len(s16_chunk) // 2
  20. # バイト列を符号付き16bit整数のタプルにアンパックする
  21. # '<' はリトルエンディアンを指定
  22. s16_samples = struct.unpack(f'<{num_samples}h', s16_chunk)
  23. # 各サンプルを符号なしに変換 (サンプル値 + 32768)
  24. u16_samples = [((s + 32768) >> 4) for s in s16_samples]
  25. # 符号なし整数のリストをバイト列にパックする
  26. # '*' はリストの要素を展開して関数の引数として渡す
  27. u16_chunk = struct.pack(f'>{num_samples}H', *u16_samples)
  28. # 変換後のチャンクを出力ファイルに書き込む
  29. outfile.write(u16_chunk)
  30. print("変換が正常に完了しました!")
  31. except FileNotFoundError:
  32. print(f"エラー: 入力ファイルが見つかりません '{input_path}'", file=sys.stderr)
  33. sys.exit(1)
  34. except Exception as e:
  35. print(f"エラーが発生しました: {e}", file=sys.stderr)
  36. sys.exit(1)
  37. if __name__ == "__main__":
  38. parser = argparse.ArgumentParser(
  39. description="RAWオーディオファイルを符号付き16bitから符号なし16bitに変換します。"
  40. )
  41. parser.add_argument("input_file", help="入力ファイルパス (signed 16-bit raw)")
  42. parser.add_argument("output_file", help="出力ファイルパス (unsigned 16-bit raw)")
  43. args = parser.parse_args()
  44. convert_s16_to_u16(args.input_file, args.output_file)