9

I have no idea how to solve this problem. Please help me :)

I would like to send sound data, recorded by one PC, to the other PC and play it. (by UDP)

The program might work correctly, but the sound contain(?) uncomfortable noise. when I tried to record & play sound in one program sequence, it worked correctly. There was no noise. In case of using UDP even in one PC, use IP 127.0.0.1, the noise appeared. At first, I thought the factor is because played sound is out in the other PC and I fixed it by making buffer. It solved little noise, but almost all the noise is still remaining.

the following code is it

Client

import pyaudio
import socket
from threading import Thread

frames = []

def udpStream():
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    

    while True:
        if len(frames) > 0:
            udp.sendto(frames.pop(0), ("127.0.0.1", 12345))

    udp.close()

def record(stream, CHUNK):    
    while True:
        frames.append(stream.read(CHUNK))

if __name__ == "__main__":
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    RATE = 44100

    p = pyaudio.PyAudio()

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

    Tr = Thread(target = record, args = (stream, CHUNK,))
    Ts = Thread(target = udpStream)
    Tr.setDaemon(True)
    Ts.setDaemon(True)
    Tr.start()
    Ts.start()
    Tr.join()
    Ts.join()

Server

import pyaudio
import socket
from threading import Thread

frames = []

def udpStream(CHUNK):

    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.bind(("127.0.0.1", 12345))

    while True:
        soundData, addr = udp.recvfrom(CHUNK)
        frames.append(soundData)

    udp.close()

def play(stream, CHUNK):
    BUFFER = 10
    while True:
            if len(frames) == BUFFER:
                while True:
                    stream.write(frames.pop(0), CHUNK)

if __name__ == "__main__":
    FORMAT = pyaudio.paInt16
    CHUNK = 1024
    CHANNELS = 2
    RATE = 44100

    p = pyaudio.PyAudio()

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

    Ts = Thread(target = udpStream, args=(CHUNK,))
    Tp = Thread(target = play, args=(stream, CHUNK,))
    Ts.setDaemon(True)
    Tp.setDaemon(True)
    Ts.start()
    Tp.start()
    Ts.join()
    Tp.join()

sorry for long source code. Feel free to play this program.

ami_GS
  • 852
  • 15
  • 21
  • Is it noisy (i.e. does the data become corrupted (e.g. due to packet loss, or due to wrong data processing)) or does it stutter (i.e. is there an issue with timing/latency/concurrency (I am not at all sure if Python's `threading` is the right choice for decoupling retrieval of the stream and playing the stream). – Dr. Jan-Philip Gehrcke Jan 16 '14 at 14:45
  • You should compare the sent and the received stuff with each other. Maybe it differs. I could imagine that the networking layer switches high and low byte on your data or similar things. That would result in drastic noise. – Alfe Jan 16 '14 at 14:48
  • @Jan-PhilipGehrcke I didn't notice about packet loss, because the version of 'image' UDP transfer worked correctly when I tried it. Thank you! I think over about packet loss and I try to do TCP implementation to compare the data. – ami_GS Jan 16 '14 at 15:20
  • @Alfe Thank you! I think you might also say about packet loss. I try compare these data. – ami_GS Jan 16 '14 at 15:23
  • Try with TCP first. If you find the performance of TCP is unreasonable then I would start looking at using UDP. – Clarus Jan 16 '14 at 18:43

2 Answers2

10

I have searched for the reason of this noise. Finally I could detect why this happened.

Actually, This program UDP transfer did not cause packet loss.

Even if it did, the sound do not have such a serious noise.


This program sent data correctly, and there are almost no packet loss, but the "receive" method could not receive data correctly.


In server program

def udpStream(CHUNK):

    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp.bind(("127.0.0.1", 12345))

    while True:
        soundData, addr = udp.recvfrom(CHUNK)
        frames.append(soundData)

    udp.close()

This program could data only "25%". (I checked the amount of data)

So, I tried to receive the data multiply (CHANNELS * 2)

        soundData, addr = udp.recvfrom(CHUNK * CHANNELS * 2)

This results in the sound data can be received 100% completely.

Finally, the sound recorded by one PC is played in the other PC without noise.

ami_GS
  • 852
  • 15
  • 21
  • The problem was related to this question (I got error 10040 on Windows): https://stackoverflow.com/questions/9378146/how-to-easily-solve-the-10040-message-too-long-error-on-wsock2. Thanks for your code, it is highly interesting for training purposes! – bomben Jun 29 '20 at 12:13
0

I've run into the same problem, but your solution didn't help me. What I discovered was that using

stream.write(frames.pop(0))

instead of

stream.write(frames.pop(0), CHUNK)

Clears all the noise in the received signal.