Résultats pour
Have you ever wondered what it takes to send live audio from one computer to another? While we use apps like Discord and Zoom every day, the core technology behind real-time voice communication is a fascinating blend of audio processing and networking. Building a simple walkie-talkie is a perfect project for demystifying these concepts, and you can do it all within the powerful environment of MATLAB.
This article will guide you through creating a functional, real-time, push-to-talk walkie-talkie. We won't be building a replacement for a commercial radio, but we will create a powerful educational tool that demonstrates the fundamentals of digital signal processing and network communication.
The Purpose: Why Build This?
The goal isn't just to talk to a colleague across the office; it's to learn by doing. By building this project, you will:
Understand Audio I/O: Learn how MATLAB interacts with your computer’s microphone and speakers.
Grasp Network Communication: See how to send data packets over a local network using the UDP protocol.
Solve Real-Time Challenges: Confront and solve issues like latency, choppy audio, and continuous data streaming.
The Core Components
Our walkie-talkie will consist of two main scripts:
Sender.m: This script will run on the transmitting computer. It listens to the microphone when a key is pressed, sending the audio data in small chunks over the network.
Receiver.m: This script runs on the receiving computer. It continuously listens for incoming data packets and plays them through the speakers as they arrive.
Step 1: Getting Audio In and Out
Before we touch networking, let's make sure we can capture and play audio. MATLAB's built-in audiorecorder and audioplayer objects make this simple.
Problem Encountered: How do you even access the microphone?
Solution: The audiorecorder object gives us straightforward control.
code
% --- Test Audio Capture and Playback ---
Fs = 8000; % Sample rate in Hz
nBits = 16; % Number of bits per sample
nChannels = 1; % Mono audio
% Create a recorder object
recObj = audiorecorder(Fs, nBits, nChannels);
disp('Start speaking for 3 seconds.');
recordblocking(recObj, 3); % Record for 3 seconds
disp('End of Recording.');
% Get the audio data
audioData = getaudiodata(recObj);
% Play it back
playObj = audioplayer(audioData, Fs);
play(playObj);
Running this script confirms that your microphone and speakers are correctly configured and accessible by MATLAB.
Step 2: Sending Voice Over the Network
Now, we need to send the audioData to another computer. For real-time applications like this, the UDP (User Datagram Protocol) is the ideal choice. It’s a "fire-and-forget" protocol that prioritizes speed over perfect reliability. Losing a tiny packet of audio is better than waiting for it to be re-sent, which would cause noticeable delays (latency).
Problem Encountered: How do you send data continuously without overwhelming the network or the receiver?
Solution: We'll send the audio in small, manageable chunks inside a loop. We need to create a UDP Port object to handle the communication.
Here's the basic structure for the Sender.m script:
code
% --- Sender.m ---
% Define network parameters
remoteIP = '192.168.1.101'; % <--- CHANGE THIS to the receiver's IP
remotePort = 3000;
localPort = 3001;
% Create UDP Port object
udpSender = udpport("LocalPort", localPort, "EnablePortSharing", true);
% Configure audio recorder
Fs = 8000;
nBits = 16;
nChannels = 1;
recObj = audiorecorder(Fs, nBits, nChannels);
disp('Press any key to start transmitting. Press Ctrl+C to stop.');
pause; % Wait for user to press a key
% Start the Push-to-Talk loop
disp('Transmitting... (Hold Ctrl+C to exit)');
while true
recordblocking(recObj, 0.1); % Record a 0.1-second chunk
audioChunk = getaudiodata(recObj);
% Send the audio chunk over UDP
write(udpSender, audioChunk, "double", remoteIP, remotePort);
end
And here is the corresponding Receiver.m script:
code
Matlab
% --- Receiver.m ---
% Define network parameters
localPort = 3000;
% Create UDP Port object
udpReceiver = udpport("LocalPort", localPort, "EnablePortSharing", true, "Timeout", 30);
% Configure audio player
Fs = 8000;
playerObj = audioplayer(zeros(Fs*0.1, 1), Fs); % Pre-buffer
disp('Listening for incoming audio...');
% Start the listening loop
while true
% Wait for and receive data
[audioChunk, ~, ~] = read(udpReceiver, Fs*0.1, "double");
if ~isempty(audioChunk)
% Play the received audio chunk
play(playerObj, audioChunk);
else
disp('No data received. Still listening...');
end
end
Step 3: Solving Real-World Hurdles
Running the code above might work, but you'll quickly notice some issues.
Problem 1: Choppy Audio and High Latency
The audio might sound robotic or delayed. This is because of the buffer size and the processing time. Sending tiny chunks frequently can cause overhead, while sending large chunks causes delay.
Solution: The key is to find a balance.
Tune the Chunk Size: The 0.1 second chunk size in the sender (recordblocking(recObj, 0.1)) is a good starting point. Experiment with values between 0.05 and 0.2. Smaller values reduce latency but increase network traffic.
Use a Buffered Player: Instead of creating a new audioplayer for every chunk, we create one at the start and feed it new data. Our receiver code already does this, which is more efficient.
Problem 2: No Real "Push-to-Talk"
Our sender script starts transmitting and doesn't stop. A real walkie-talkie only transmits when a button is held down.
Solution: Simulating this in a script requires a more advanced technique, ideally using a MATLAB App Designer GUI. However, we can create a simple command-window version using a figure's KeyPressFcn.
Here is an improved concept for the Sender that simulates radio push-to-talk, e.g. https://www.retevis.com/blog/ptt-push-to-talk-walkie-talkies-guide
% --- Advanced_Sender.m ---
function PushToTalkSender()
% -- Configuration --
remoteIP = '192.168.1.101'; % <--- CHANGE THIS
remotePort = 3000;
localPort = 3001;
Fs = 8000;
% -- Setup --
udpSender = udpport("LocalPort", localPort);
recObj = audiorecorder(Fs, 16, 1);
% -- GUI for key press detection --
fig = uifigure('Name', 'Push-to-Talk (Hold ''t'')', 'Position', [100 100 300 100]);
fig.KeyPressFcn = @KeyPress;
fig.KeyReleaseFcn = @KeyRelease;
isTransmitting = false; % Flag to control transmission
disp('Focus on the figure window. Hold the ''t'' key to transmit.');
% --- Main Loop ---
while ishandle(fig)
if isTransmitting
% Non-blocking record and send would be ideal,
% but for simplicity we use short blocking chunks.
recordblocking(recObj, 0.1);
audioChunk = getaudiodata(recObj);
write(udpSender, audioChunk, "double", remoteIP, remotePort);
disp('Transmitting...');
else
pause(0.1); % Don't burn CPU when idle
end
drawnow; % Update figure window
end
% --- Callback Functions ---
function KeyPress(~, event)
if strcmp(event.Key, 't')
isTransmitting = true;
end
end
function KeyRelease(~, event)
if strcmp(event.Key, 't')
isTransmitting = false;
disp('Transmission stopped.');
end
end
end
Conclusion and Next Steps
You've now built the foundation of a real-time voice communication tool in MATLAB! You've learned how to capture audio, send it over a network using UDP, and handle some of the fundamental challenges of real-time streaming.
This project is the perfect starting point for more advanced explorations:
Build a Full GUI: Use App Designer to create a user-friendly interface with a proper push-to-talk radio button.
Implement Noise Reduction: Apply a filter (e.g., a simple low-pass or a more advanced spectral subtraction algorithm) to the audioChunk before sending it.
Add Channels: Modify the code to use different UDP ports, allowing users to select a "channel" to talk on.