Требования:
- 1 устройство (например, телефон) с ВЫХОДНОЙ ЛИНЕЙНОЙ линией (гнездо AUX 3,5 мм)
- 1 специальный кабель (стереоразъем AUX 3,5 мм «штекер» к 3 проводам (земля, левый канал, правый канал)< /li>
1 Arduino Mega 2560 - 1 USB типа A — USB
- 1 компьютер со следующим установленным программным обеспечением:
Arduino IDE или эквивалент для разработки Arduino - Java JDK >= 8
- VSCode или эквивалент для разработки на Java
Цель моего проекта — захватить аудио с устройства (например, телефона или телевизора) и отправить его на компьютер.< /p>
Я создал драйверы для перенаправления аудиопотока, но слышу потрескивание в динамиках, но могу распознать мелодию, несмотря на потрескивание.
Мой специальный кабель подключается к AUX устройства (телефона), а провода этого кабеля подключены к плате Arduino Mega 2560 к контактам аналогового входа (земля -> GND, левый канал -> A0, правый канал -> A1).
Кабель USB подключен к Arduino и к компьютеру.
Arduino подключен к питанию.
Я написал программу на Arduino для пересылки входящего звука с аналоговых контактов на последовательный порт (USB).
Я написал этот исходный код, который работает на Arduino:
Код: Выделить всё
const int SAMPLE_RATE = 44100; // Fréquence d'échantillonnage en Hz
const unsigned long SAMPLE_INTERVAL = 1000000.0 / SAMPLE_RATE; // Intervalle d'échantillonnage en microsecondes
void setup() {
Serial.begin(115200); // Initialiser la communication série à une vitesse plus élevée pour éviter la perte de données
}
void loop() {
static unsigned long lastSampleTime = 0;
if (micros() - lastSampleTime >= SAMPLE_INTERVAL) {
lastSampleTime += SAMPLE_INTERVAL;
// Lire les valeurs analogiques
int leftSample = analogRead(A0);
int rightSample = analogRead(A1);
// Convertir les valeurs analogiques en valeurs audio (-32768 à 32767)
int16_t leftAudio = map(leftSample, 0, 1023, -32768, 32767);
int16_t rightAudio = map(rightSample, 0, 1023, -32768, 32767);
// Envoyer les données audio via le port série (USB) sous forme brute
Serial.write(0xFF);
Serial.write(lowByte(leftSample));
Serial.write(highByte(leftSample));
Serial.write(lowByte(rightSample));
Serial.write(highByte(rightSample));
}
}
Код: Выделить всё
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
import com.fazecast.jSerialComm.SerialPortEvent;
import io.nirahtech.soundpack.box.driver.AudioFrame;
import io.nirahtech.soundpack.box.driver.Sample;
public class Jack2Usb2Audio {
private static final int SAMPLE_RATE = 44100; // Fréquence d'échantillonnage en Hz
private static final int BITS_PER_SAMPLE = 16; // Taille en bits d'un échantillon
private static final int SAMPLE_SIZE = BITS_PER_SAMPLE / 8; // Taille d'un échantillon
private static final int CHANNELS = 2; // Nombre de canaux (stéréo)
private static final int FRAME_SIZE = SAMPLE_SIZE * CHANNELS; // Taille du cadre audio en octets, ici = 4
private static final int BUFFER_SIZE = FRAME_SIZE * 1024; // Taille du buffer en octets
private static final int SERIAL_BAUD_RATE = 115200; // Taux de baud
private static final String SERIAL_PORT = "/dev/ttyACM0"; // Port USB
private static final byte START_OF_FRAME = (byte) 0xFF;
public static void main(String[] args) {
SerialPort serialPort = SerialPort.getCommPort(SERIAL_PORT);
serialPort.setBaudRate(SERIAL_BAUD_RATE);
serialPort.setNumDataBits(8);
serialPort.setNumStopBits(SerialPort.ONE_STOP_BIT);
serialPort.setParity(SerialPort.NO_PARITY);
if (!serialPort.openPort()) {
System.out.println("Échec de l'ouverture du port.");
return;
}
System.out.println("Port ouvert avec succès.");
AudioFormat format = new AudioFormat(SAMPLE_RATE, BITS_PER_SAMPLE, CHANNELS, true, false);
try {
SourceDataLine line = AudioSystem.getSourceDataLine(format);
line.open(format);
line.start();
serialPort.addDataListener(new SerialPortDataListener() {
private boolean isNewSampleCycleStarted = false;
private List cache = new ArrayList();
private AudioFrame audioFrame = new AudioFrame(FRAME_SIZE * 8);
@Override
public int getListeningEvents() {
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
return;
}
byte[] newSamples = new byte[serialPort.bytesAvailable()];
int totalSamplesRetrieved = serialPort.readBytes(newSamples, newSamples.length);
for (int i = 0; i < totalSamplesRetrieved; i++) {
final byte receivedSample = newSamples[i];
if (receivedSample == START_OF_FRAME) {
this.audioFrame = new AudioFrame(FRAME_SIZE * 8);
} else {
if (!this.isNewSampleCycleStarted) {
this.cache.add(receivedSample);
this.isNewSampleCycleStarted = true;
} else {
this.isNewSampleCycleStarted = false;
if (!this.cache.isEmpty()) {
final byte previousSample = this.cache.get(0);
this.cache.clear();
final Sample sample = Sample.of(previousSample, receivedSample);
if (!this.audioFrame.hasSpaceLeft()) {
this.audioFrame = new AudioFrame(FRAME_SIZE * 8);
}
try {
this.audioFrame.addSample(sample);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (!this.audioFrame.hasSpaceLeft()) {
byte[] data = this.audioFrame.toBytes();
line.write(data, 0, this.audioFrame.getUsedSizeInBits());
}
}
}
}
});
System.out.println("Lecture audio en cours. Appuyez sur Enter pour arrêter.");
System.in.read();
line.stop();
line.close();
} catch (LineUnavailableException | IOException e) {
e.printStackTrace();
} finally {
serialPort.closePort();
System.out.println("Port fermé.");
}
}
}
package io.nirahtech.soundpack.box.driver;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class AudioFrame {
private final List samples;
private final int maxSizeInBits;
public AudioFrame(final int sizeInBits) {
this.maxSizeInBits = sizeInBits;
this.samples = new ArrayList();
}
public int getMaxSizeInBits() {
return this.maxSizeInBits;
}
public int getUsedSizeInBits() {
return (int) this.samples.stream().mapToInt(Sample::getSizeInBits).sum();
}
public int getEmptySizeInBits() {
return this.getMaxSizeInBits() - this.getUsedSizeInBits();
}
public boolean hasSpaceLeft() {
return this.getUsedSizeInBits() < this.getMaxSizeInBits();
}
public void addSample(final Sample sample) throws Exception {
Objects.requireNonNull(sample, "Sample is required for AudioFrame.");
if (!this.hasSpaceLeft()) {
throw new Exception("No space left");
}
this.samples.add(sample);
}
public byte[] toBytes() {
final byte[] frame = new byte[this.maxSizeInBits];
int frameIndex = 0;
for (final Sample sample : this.samples) {
final byte[] sampleAsBytes = sample.toBytes();
for (byte sampleBit : sampleAsBytes) {
frame[frameIndex] = sampleBit;
frameIndex++;
}
}
return frame;
}
}
package io.nirahtech.soundpack.box.driver;
public class Sample {
private final short sample;
private final byte lowByte;
private final byte highByte;
private Sample(final short sample) {
this.sample = sample;
this.lowByte = (byte) (this.sample & 0xFF);
this.highByte = (byte) ((this.sample >> 8) & 0xFF);
}
public int getSizeInBits() {
return 8 * 2;
}
public byte getLowByte() {
return this.lowByte;
}
public byte getHighByte() {
return this.highByte;
}
public static final Sample of(final short sample) {
return new Sample(sample);
}
public static final Sample of(final byte lowByte, final byte highByte) {
final short sample = (short) ((highByte
Подробнее здесь: [url]https://stackoverflow.com/questions/78549655/how-forward-sound-from-output-line-to-usb[/url]
Мобильная версия