Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compressed audio #36

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions audioread/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,45 +68,45 @@ def _mad_available():
return True


def audio_open(path):
def audio_open(path=None, audio=None):
"""Open an audio file using a library that is available on this
system.
"""
# Standard-library WAV and AIFF readers.
from . import rawread
try:
return rawread.RawAudioFile(path)
except DecodeError:
pass
#from . import rawread
#try:
# return rawread.RawAudioFile(path)
#except DecodeError:
# pass

# Core Audio.
if _ca_available():
from . import macca
try:
return macca.ExtAudioFile(path)
except DecodeError:
pass
#if _ca_available():
# from . import macca
# try:
# return macca.ExtAudioFile(path)
# except DecodeError:
# pass

# GStreamer.
if _gst_available():
from . import gstdec
try:
return gstdec.GstAudioFile(path)
except DecodeError:
pass
#if _gst_available():
# from . import gstdec
# try:
# return gstdec.GstAudioFile(path)
# except DecodeError:
# pass

# MAD.
if _mad_available():
from . import maddec
try:
return maddec.MadAudioFile(path)
except DecodeError:
pass
#if _mad_available():
# from . import maddec
# try:
# return maddec.MadAudioFile(path)
# except DecodeError:
# pass

# FFmpeg.
from . import ffdec
try:
return ffdec.FFmpegAudioFile(path)
return ffdec.FFmpegAudioFile(path,audio)
except DecodeError:
pass

Expand Down
Binary file added audioread/__init__.pyc
Binary file not shown.
62 changes: 50 additions & 12 deletions audioread/ffdec.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import threading
import time
import os
from cStringIO import StringIO
try:
import queue
except ImportError:
Expand Down Expand Up @@ -51,11 +52,13 @@ class NotInstalledError(FFmpegError):
class ReadTimeoutError(FFmpegError):
"""Reading from the ffmpeg command-line tool timed out."""

class NoInputError(FFmpegError):
"""Reading from the ffmpeg command-line tool timed out."""

class QueueReaderThread(threading.Thread):
"""A thread that consumes data from a filehandle and sends the data
over a Queue.
"""
"""
def __init__(self, fh, blocksize=1024, discard=False):
super(QueueReaderThread, self).__init__()
self.fh = fh
Expand All @@ -67,12 +70,25 @@ def __init__(self, fh, blocksize=1024, discard=False):
def run(self):
while True:
data = self.fh.read(self.blocksize)
#print data
if not self.discard:
self.queue.put(data)
if not data:
# Stream closed (EOF).
break

class WriterThread(threading.Thread):
"""A thread that writes data to a filehandle
"""
def __init__(self, fh, audio=None):
super(WriterThread, self).__init__()
self.fh = fh
self.audio = audio
self.daemon = True

def run(self):
self.fh.write(self.audio.read())
self.fh.close()

def popen_multiple(commands, command_args, *args, **kwargs):
"""Like `subprocess.Popen`, but can try multiple commands in case
Expand Down Expand Up @@ -100,7 +116,10 @@ def popen_multiple(commands, command_args, *args, **kwargs):

class FFmpegAudioFile(object):
"""An audio file decoded by the ffmpeg command-line utility."""
def __init__(self, filename, block_size=4096):
def __init__(self, filename=None, audio=None, block_size=4096):
self.openFile = True if filename is not None else False
self.readAudio = True if audio is not None else False

# On Windows, we need to disable the subprocess's crash dialog
# in case it dies. Passing SEM_NOGPFAULTERRORBOX to SetErrorMode
# disables this behavior.
Expand All @@ -116,16 +135,28 @@ def __init__(self, filename, block_size=4096):
ctypes.windll.kernel32.SetErrorMode(
previous_error_mode | SEM_NOGPFAULTERRORBOX
)

try:
self.devnull = open(os.devnull)
self.proc = popen_multiple(
COMMANDS,
['-i', filename, '-f', 's16le', '-'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=self.devnull,
)
if self.openFile:
self.devnull = open(os.devnull)
self.proc = popen_multiple(
COMMANDS,
['-i', filename, '-f', 's16le', '-'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=self.devnull,
)
elif self.readAudio:
self.devnull = open(os.devnull)
self.proc = popen_multiple(
COMMANDS,
['-i', '-', '-f', 's16le', '-'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
)
else:
raise NoInputError()

except OSError:
raise NotInstalledError()
Expand All @@ -141,11 +172,16 @@ def __init__(self, filename, block_size=4096):
finally:
windows_error_mode_lock.release()

# Start a thread to write the compressed audio to Popen.stdin
if self.readAudio:
self.stdin_writer = WriterThread(self.proc.stdin,audio)
self.stdin_writer.start()

# Start another thread to consume the standard output of the
# process, which contains raw audio data.
self.stdout_reader = QueueReaderThread(self.proc.stdout, block_size)
self.stdout_reader.start()

# Read relevant information from stderr.
self._get_info()

Expand All @@ -165,6 +201,7 @@ def read_data(self, timeout=10.0):
data = None
try:
data = self.stdout_reader.queue.get(timeout=timeout)

if data:
yield data
else:
Expand Down Expand Up @@ -192,6 +229,7 @@ def _get_info(self):
out_parts = []
while True:
line = self.proc.stderr.readline()

if not line:
# EOF and data not found.
raise CommunicationError("stream info not found")
Expand Down
Binary file added audioread/ffdec.pyc
Binary file not shown.
Binary file added audioread/gstdec.pyc
Binary file not shown.
Binary file added audioread/rawread.pyc
Binary file not shown.
4 changes: 3 additions & 1 deletion decode.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/python

# This file is part of audioread.
# Copyright 2011, Adrian Sampson.
#
Expand Down Expand Up @@ -28,7 +30,7 @@ def decode(filename):
sys.exit(1)

try:
with audioread.audio_open(filename) as f:
with audioread.audio_open(audio=open(filename,"r")) as f:
print('Input file: %i channels at %i Hz; %.1f seconds.' %
(f.channels, f.samplerate, f.duration),
file=sys.stderr)
Expand Down