12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- #!/usr/bin/env python3
- """Load an audio file into memory and play its contents.
- NumPy and the soundfile module (https://python-soundfile.readthedocs.io/)
- must be installed for this to work.
- This example program loads the whole file into memory before starting
- playback.
- To play very long files, you should use play_long_file.py instead.
- This example could simply be implemented like this::
- import sounddevice as sd
- import soundfile as sf
- data, fs = sf.read('my-file.wav')
- sd.play(data, fs)
- sd.wait()
- ... but in this example we show a more low-level implementation
- using a callback stream.
- """
- import argparse
- import threading
- import sounddevice as sd
- import soundfile as sf
- def int_or_str(text):
- """Helper function for argument parsing."""
- try:
- return int(text)
- except ValueError:
- return text
- parser = argparse.ArgumentParser(add_help=False)
- parser.add_argument(
- '-l', '--list-devices', action='store_true',
- help='show list of audio devices and exit')
- args, remaining = parser.parse_known_args()
- if args.list_devices:
- print(sd.query_devices())
- parser.exit(0)
- parser = argparse.ArgumentParser(
- description=__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter,
- parents=[parser])
- parser.add_argument(
- 'filename', metavar='FILENAME',
- help='audio file to be played back')
- parser.add_argument(
- '-d', '--device', type=int_or_str,
- help='output device (numeric ID or substring)')
- args = parser.parse_args(remaining)
- event = threading.Event()
- try:
- data, fs = sf.read(args.filename, always_2d=True)
- current_frame = 0
- def callback(outdata, frames, time, status):
- global current_frame
- if status:
- print(status)
- chunksize = min(len(data) - current_frame, frames)
- outdata[:chunksize] = data[current_frame:current_frame + chunksize]
- if chunksize < frames:
- outdata[chunksize:] = 0
- raise sd.CallbackStop()
- current_frame += chunksize
- stream = sd.OutputStream(
- samplerate=fs, device=args.device, channels=data.shape[1],
- callback=callback, finished_callback=event.set)
- with stream:
- event.wait() # Wait until playback is finished
- except KeyboardInterrupt:
- parser.exit('\nInterrupted by user')
- except Exception as e:
- parser.exit(type(e).__name__ + ': ' + str(e))
|