题外话:首先让我说 Java 对我来说是全新的。我已经编程超过 15 年了,除了修改其他人的代码库之外,从来没有需要它,所以请原谅我的无知和可能不恰当的术语。我对射频也不是很熟悉,所以如果我在这里很陌生,请告诉我!
我正在构建一个 SDR(软件定义无线电)无线电发射器,虽然我可以在某个频率上成功传输,但当我发送流(来自设备的麦克风或来自音调发生器的字节)时,我的手持接收器会发出什么听起来像静态的。
我相信这是由于我的接收器设置为接收 NFM(窄带频率调制)和 WFM(宽带频率调制),而来自我的 SDR 的传输正在发送原始的、未调制的数据。
我的问题是:如何调制音频字节(即InputStream),以便在FM(频率调制)或AM(幅度调制)中调制得到的字节,然后我可以通过 SDR 传输?
尽管有很多开源软件,但我似乎找不到处理调制的类或包(最终我将不得不调制 WFM、FM、AM、SB、LSB、USB、DSB 等) SDR 代码库,但如果你知道我在哪里可以找到它,那基本上就回答了这个问题。到目前为止,我发现的一切都是为了解调。
这是我在 StackOverflow 上围绕Xarph's Answer构建的一个类,它只返回一个包含简单、未调制的音频信号的字节数组,然后可用于通过扬声器播放声音(或通过 SDR 传输,但由于结果没有被正确调制,它在接收器端没有正确通过,这是我无法弄清楚的)
public class ToneGenerator {
public static byte[] generateTone() {
return generateTone(60, 1000, 8000);
}
public static byte[] generateTone(double duration) {
return generateTone(duration, 1000, 8000);
}
public static byte[] generateTone(double duration, double freqOfTone) {
return generateTone(duration, freqOfTone, 8000);
}
public static byte[] generateTone(double duration, double freqOfTone, int sampleRate) {
double dnumSamples = duration * sampleRate;
dnumSamples = Math.ceil(dnumSamples);
int numSamples = (int) dnumSamples;
double sample[] = new double[numSamples];
byte generatedSnd[] = new byte[2 * numSamples];
for (int i = 0; i < numSamples; ++i) { // Fill the sample array
sample[i] = Math.sin(freqOfTone * 2 * Math.PI * i / (sampleRate));
}
// convert to 16 bit pcm sound array
// assumes the sample buffer is normalized.
// convert to 16 bit pcm sound array
// assumes the sample buffer is normalised.
int idx = 0;
int i = 0 ;
int ramp = numSamples / 20 ; // Amplitude ramp as a percent of sample count
for (i = 0; i< ramp; ++i) { // Ramp amplitude up (to avoid clicks)
double dVal = sample[i];
// Ramp up to maximum
final short val = (short) ((dVal * 32767 * i/ramp));
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}
for (i = i; i< numSamples - ramp; ++i) { // Max amplitude for most of the samples
double dVal = sample[i];
// scale to maximum amplitude
final short val = (short) ((dVal * 32767));
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}
for (i = i; i< numSamples; ++i) { // Ramp amplitude down
double dVal = sample[i];
// Ramp down to zero
final short val = (short) ((dVal * 32767 * (numSamples-i)/ramp ));
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}
return generatedSnd;
}
}
这个问题的答案不一定需要代码,实际上是理论和理解 FM 或 AM 调制在处理字节数组并将其转换为正确格式时的工作原理可能更有价值,因为我将拥有未来实施更多模式。