2323parser = argparse .ArgumentParser (description = __doc__ )
2424parser .add_argument ('filename' , help = 'audio file to be played back' )
2525parser .add_argument (
26- '-b' , '--buffersize' , type = int , default = 10 ,
26+ '-b' , '--buffersize' , type = int , default = 20 ,
2727 help = 'number of blocks used for buffering (default: %(default)s)' )
2828parser .add_argument ('-c' , '--clientname' , default = 'file player' ,
2929 help = 'JACK client name' )
3333if args .buffersize < 1 :
3434 parser .error ('buffersize must be at least 1' )
3535
36- callback2disk = queue .Queue (maxsize = 1 )
37- disk2callback = queue .Queue (maxsize = 1 )
36+ q = queue .Queue (maxsize = args .buffersize )
3837event = threading .Event ()
3938
4039
@@ -63,27 +62,20 @@ def stop_callback(msg=''):
6362
6463
6564def process (frames ):
66- global callback_buffer , callback_counter
6765 if frames != blocksize :
6866 stop_callback ('blocksize must not be changed, I quit!' )
69- if callback_counter == 0 :
70- try :
71- callback2disk .put_nowait (callback_buffer )
72- callback_buffer , callback_counter = disk2callback .get_nowait ()
73- except (queue .Full , queue .Empty ):
74- stop_callback ('Buffer error: increase buffersize?' )
75- if callback_counter == 0 : # Playback is finished
76- stop_callback ()
77- idx = (args .buffersize - callback_counter ) * blocksize
78- block = callback_buffer [idx :idx + blocksize ]
79- for channel , port in zip (block .T , client .outports ):
67+ try :
68+ data = q .get_nowait ()
69+ except queue .Empty :
70+ stop_callback ('Buffer is empty: increase buffersize?' )
71+ if data is None :
72+ stop_callback () # Playback is finished
73+ for channel , port in zip (data .T , client .outports ):
8074 port .get_array ()[:] = channel
81- callback_counter -= 1
8275
8376
8477try :
8578 import jack
86- import numpy as np
8779 import soundfile as sf
8880
8981 client = jack .Client (args .clientname )
@@ -94,28 +86,15 @@ def process(frames):
9486 client .set_process_callback (process )
9587
9688 with sf .SoundFile (args .filename ) as f :
97- block_generator = f .blocks (blocksize = blocksize , dtype = 'float32' ,
98- always_2d = True , fill_value = 0 )
99-
100- def fill_buffer (buf ):
101- nr = - 1 # For the case that block_generator is already exhausted
102- for nr , block in zip (range (args .buffersize ), block_generator ):
103- idx = nr * blocksize
104- buf [idx :idx + blocksize ] = block
105- return nr + 1 # Number of valid blocks, the rest is garbage
106-
107- # Initialize first audio buffer to be played back
108- buffer = np .empty ([blocksize * args .buffersize , f .channels ])
109- valid_blocks = fill_buffer (buffer )
110- disk2callback .put_nowait ((buffer , valid_blocks ))
111-
112- # Initialize second buffer
113- callback_buffer = np .empty ([blocksize * args .buffersize , f .channels ])
114- callback_counter = 0
115-
11689 for ch in range (f .channels ):
11790 client .outports .register ('out_{0}' .format (ch + 1 ))
118-
91+ block_generator = f .blocks (blocksize = blocksize , dtype = 'float32' ,
92+ always_2d = True , fill_value = 0 )
93+ try :
94+ for data in block_generator :
95+ q .put_nowait (data )
96+ except queue .Full :
97+ pass
11998 with client :
12099 if not args .manual :
121100 target_ports = client .get_ports (
@@ -127,16 +106,14 @@ def fill_buffer(buf):
127106 else :
128107 for source , target in zip (client .outports , target_ports ):
129108 source .connect (target )
130-
131109 timeout = blocksize * args .buffersize / samplerate
132- while valid_blocks :
133- buffer = callback2disk .get (timeout = timeout )
134- valid_blocks = fill_buffer (buffer )
135- disk2callback .put ((buffer , valid_blocks ), timeout = timeout )
136- event .wait ()
110+ for data in block_generator :
111+ q .put (data , timeout = timeout )
112+ q .put (None , timeout = timeout ) # Signal end of file
113+ event .wait () # Wait until playback is finished
137114except KeyboardInterrupt :
138115 parser .exit ('\n Interrupted by user' )
139- except (queue .Empty , queue . Full ):
116+ except (queue .Full ):
140117 # A timeout occured, i.e. there was an error in the callback
141118 parser .exit (1 )
142119except Exception as e :
0 commit comments