ElectronicZoologyfield notes from the garage
← Back
Linux basics

Saving a Script File

How to save a block of code as a runnable file

A script is just a plain text file. There is nothing special about it - the code you copy from this guide goes into a file, you give it a name ending in .py, and Python can then run it.

What you are going to do

  1. Open a new file in a text editor
  2. Paste the script into it
  3. Save it as wav_to_i2s_header_multi.py
  4. Run it from the terminal

Step 1 - Open a file

Option 1 - nano (terminal, no install needed)

Open a terminal and type:

nano wav_to_i2s_header_multi.py

This opens a blank file in the terminal editor, ready to paste into.

Option 2 - any text editor (VS Code, Kate, gedit, etc.)

Open your text editor and create a new file.

Step 2 - Paste the script

Copy this and paste it into the file you just opened.

import sys, wave, struct

input_file  = sys.argv[1]
output_file = sys.argv[2]
var_name    = sys.argv[3] if len(sys.argv) > 3 else 'audio'

with wave.open(input_file, 'rb') as f:
    raw = f.readframes(f.getnframes())

samples = struct.unpack('<' + str(len(raw)//2) + 'h', raw)

lines = [
    '#pragma once',
    '#include <pgmspace.h>',
    'const int16_t ' + var_name + '_data[] PROGMEM = {',
]
chunks = [str(s) for s in samples]
for i in range(0, len(chunks), 16):
    lines.append('  ' + ', '.join(chunks[i:i+16]) + ',')
lines.append('};')
lines.append('const size_t ' + var_name + '_len = sizeof(' + var_name + '_data);')

with open(output_file, 'w') as f:
    f.write('\n'.join(lines) + '\n')

print('Done: ' + str(len(samples)) + ' samples -> ' + output_file)

Step 3 - Save and close

nano: press Ctrl+O, then Enter to confirm the filename, then Ctrl+X to exit.

Text editor: save as wav_to_i2s_header_multi.py. Make sure it saves as plain text - not a Word document or rich text file. Your home folder (/home/yourname/) or a project folder works well.

Step 4 - Run it

Run this from the terminal with all your WAV files in ~/myclips/. It converts each clip and generates a .h file for each one:

for f in ~/myclips/*.wav; do
  name=$(basename "$f" .wav)
  ffmpeg -y -i "$f" -ar 22050 -ac 1 -acodec pcm_s16le "/tmp/${name}_i2s.wav"
  python3 ~/wav_to_i2s_header_multi.py "/tmp/${name}_i2s.wav" "${name}.h" "$name"
done

Place all the generated .h files in your sketch folder - the same directory as your .ino file.

Sample rate: the -ar 22050 value must match SAMPLE_RATE in the sketch or clips will play at the wrong speed. Run your own tests - what sounds acceptable depends on your speaker and use case. 8000 works well on many speakers and produces much smaller files.

Key details

  • A script is just a plain text file with code inside
  • The filename extension (.py) tells Linux what it is
  • Any text editor works - nano, gedit, VS Code, Kate
  • Save it somewhere you can find it - your home folder is fine