Simultane Aufnahme / Wiedergabe mit Thread

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DerIng
User
Beiträge: 3
Registriert: Freitag 20. November 2015, 12:43

Hallo allerseits,
Im Rahmen meiner Studienarbeit soll ich untersuchen, ob die Soundkarte des Rechners zur Radarsignalverarbeitung geeignet ist. Hierzu wird ein Signal (Sägezahn) aus dem Kopfhörerausgang an das Radar geschickt und das empfangene Signal wird über die Mikrofonschnittstelle eingelesen. Da es sich beim Radar um das FMCW- Prinzip handelt muss das Senden und Empfangen simultan geschehen. Ich habe in Python soweit ein kleines Programm geschrieben , welches ein Sinussignal f=400 Hz schickt und direkt über die MIC- Schnittstelle wieder aufnimmt. Das aufgenommene Signal wird in eine wav. Datei geschrieben, um es dann in MATLAB / Audacity auszuwerten. Jedoch habe ich festgestellt, dass die Aufnahme und die Wiedergabe nicht exakt zeitgleich laufen. Mein Code, der zur Testzwecken dient ist wie folgt:

Code: Alles auswählen

#!/usr/bin/env python

import pyaudio
import wave
import sys
import time
import math
from math import *
from getopt import *
import threading
import scipy
from scipy import signal
import numpy as np
import matplotlib.pyplot as plt



def Th1():
    while time.time() <= start_time:
        pass
    threading.Thread(target=record_audio(1)).start()

def Th2():
    while time.time() <= start_time:
        pass
    threading.Thread(target=play_audio(0.5)).start()


def sin_wave(f0=200,A=10000,fs=48000,length=1.):

  n=int(fs*length)
  wav=''

  for i in range(0, n):
    TX=int(A*math.sin(i*2*np.pi*f0/fs))
    wav += chr(TX & 0xFF) + chr((TX & 0xFF00) >> 8)
  return wav


def make_sawtooth(f0=500,A=100):
  t=np.linspace(0,1,f0)
  wav2=''
  for i in range(0,f0):
    Saw=int(A*signal.sawtooth(2*np.pi*5*t*i))
  return Saw


def play_audio(forHowLong):
    #data= make_sawtooth(f0=400,A=1)
    data2= sin_wave(f0=400,A=600,fs=22050,length=1.)

    p = pyaudio.PyAudio() #sets up portaudio system
    stream = p.open(format=p.get_format_from_width(2),
                channels=1,
                rate=22050,
                output=True)

    start = time.time()
    while time.time() < start + forHowLong*0.5:
            stream.write(data2)
     stream.stop_stream()
    stream.close()
    p.terminate()


def record_audio(forHowLong):
    NUM_SAMPLES = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 96000
    RECORD_SECONDS = forHowLong
    WAVE_OUTPUT_FILENAME = "output.wav"

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
            channels=CHANNELS,
            rate=RATE,
            input=True,
            frames_per_buffer=NUM_SAMPLES)

    print("* recording")

    frames = []

    for i in range(0, int(RATE / NUM_SAMPLES * RECORD_SECONDS)):
      data = stream.read(NUM_SAMPLES)
      frames.append(data)

    print("* done recording")

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

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()



start_time=time.time()+0.25


threading.Thread(target=Th2).start()
threading.Thread(target=Th1).start()


Wie bekomme ich es am Besten hin, dass die beiden Funktionen exakt zeitgleich laufen?
Danke im Voraus! Viele Grüße
Zuletzt geändert von Anonymous am Freitag 20. November 2015, 18:03, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerIng: die Threads sind falsch. Das Starten eines Threads innerhalb deines Threads ist falsch, und sowieso unnötig. Statt eines busy-loops wäre sleep das richtige.

Code: Alles auswählen

def record_thread(start_time):
    time.sleep(start_time - time.time())
    record_audio(1)

def play_thread(start_time):
    time.sleep(start_time - time.time())
    play_audio(0.5)

def main():
    start_time = time.time()+0.25
    threading.Thread(target=play_thread, args=(start_time,)).start()
    threading.Thread(target=record_thread, args=(start_time,)).start()

if __name__ == '__main__':
    main()
Sternchenimporte sind schlecht und werden hier auch gar nicht benutzt.
DerIng
User
Beiträge: 3
Registriert: Freitag 20. November 2015, 12:43

@Sirius3: Danke das hat soweit geklappt.
Antworten