Make python code run faster to reduce offset
<p>I am currently working on a project using python. My objective is to be able to make an active noise cancelling device using a Raspberry Pi. 
For now, I've written this program, which starts recording the sound I'm trying to cancel, then uses a PID controler to calculate an inverted wave to the original one and plays it, in order to cancel it. </p>

<p>My problem now is that the program takes some time to do the math, so once it has calculated the inverted wave, the original one has already passed by the device, and I get an offset of aproximately 0.02 seconds. My goal is to reduce this offset as much as possible, and then compensate it by increasing the distance between the microphone and the speaker. Right now, as the offset is 0.02 seconds, and the speed of sound is 340 m/s, I would have to set that distance to 6.8 meters (0.02 * 340 = 6.8), and that's too much.</p>

<p>So how can I make the program run faster?
Here's the code:</p>

<pre><code>import pyaudio, math, struct
import numpy as np
import matplotlib.pyplot as plt

#INITIAL CONFIG

chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = float(input('Seconds: '))

p = pyaudio.PyAudio()
guess = 0
integral = 0
kp = 0.5
ki = 200
kd = 9999
dt = RATE**(-1)
ddt = RATE
stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                output=True,
                frames_per_buffer=chunk)

total_error = 0
previous_e = 0

#Start processing
print ("* recording")

for i in range(0, int(RATE / chunk * RECORD_SECONDS)):
    byted = (b'')
    for element in np.fromstring(stream.read(chunk), 'Int16'):
        error = -(guess - element)
        integral += error*dt
        derivative = (error - previous_e) / ddt
        guess += int(round(kp*error + ki*integral + kd*derivative, 0))
        byted += struct.pack('&lt;h', -guess)
        previous_e = error
    stream.write(byted, chunk)

#Close
stream.stop_stream()
stream.close()
p.terminate()

input ('Press enter to exit...')
</code></pre>

<p>Please note: Do not only respond with a solution, please explain why does it improve the speed of the program, as not only I want this to work but I also want to learn.</p>

<p>Thanks</p>

<p>My rough simulation indicates that you might gain some speed by not concatenating byte strings in your loop but instead collecting them in an array and joining them after your loop:</p>

<pre><code>byted_array = []
    for element in np.fromstring(stream.read(chunk), 'Int16'):
        ...
        byted_array.append(struct.pack('&lt;h', -guess))
        ...
    stream.write(b''.join(byted_array), chunk)
</code></pre>

python performance audio pid