Max Pie
Max Pie

Reputation: 99

Redirecting audio output from one function to another function in python

Suppose I have two functions drawn from two different APIs, function A and B.

By default, function A outputs audio data to a wav file.

By default, function B takes audio input from a wav file and process it.

Is it possible to stream the data from function A to B? If so, how do I do this? I work on lubuntu if that is relevant.

This is function A I'm thinking about from the PJSUA python API:

create_recorder(self, filename) Create WAV file recorder.

Keyword arguments filename -- WAV file name

Return: WAV recorder ID

And this is function B from the Pocketsphinx Python API

decode_raw(...)

Decode raw audio from a file. Parameters: fh (file) - Filehandle to read audio from. uttid (str) - Identifier to give to this utterance. maxsamps (int) - Maximum number of samples to read. If not specified or -1, the rest of the file will be read.

update:

When I try to pass the filename of a socket or named pipe, it outputs this error message, seems that the C function that the python bindings use doesn't like anything but .wav files... Why would that be?

pjsua_aud.c .pjsua_recorder_create() error: unable to determine file format for /tmp/t_fifo. Exception: Object: LIb, operation=create(recorder), error=Option/operation is not supported (PJ_ENOTSUP)

I need to use a value returned by create_recorder(), it is an int that is used to get the wav recorder id (which is not passed on directly to decode_raw() but rather passed on to some other function.

Upvotes: 1

Views: 1269

Answers (2)

jfs
jfs

Reputation: 414915

You could use a named pipe os.mkfifo() and move functions to different threads/processes e.g.:

import os
from multiprocessing import Process

os.mkfifo(filename)
try:
    Process(target=obj.create_recorder, args=[filename]).start()
    decode_raw(filename, ...)
finally:
    os.remove(filename)

Upvotes: 1

Max DeLiso
Max DeLiso

Reputation: 1244

The answer is highly platform dependent and more details are required. Different Operating Systems have different ways of handling Interprocess Communication, or IPC.

If you're using a UNIXlike environment, there are a rich set of IPC primitives to work with. Pipes, SYS V Message Queues, shared memory, sockets, etc. In your case I think it would make sense to use a pipe or a socket, depending on whether the A and B are running in the same process or not.

Update:

In your case, I would use python's subprocess and or os module and a pipe. The idea here is to create calling contexts to the two APIs in processes which share a parent process, which has also created a unidirectional named pipe and passed it to its children. Then, data written to the named pipe in create_recorder will immediately be available for read()ing in the named pipe.

Upvotes: 2

Related Questions