检索和解码调幅sin

时间:2018-02-19 19:58:50

标签: java android audio signal-processing

对于我的文凭,我需要对音频中的一些数据进行编码,通过扬声器播放,在其他Android手机上重现此音频并对其进行解码。对于这种情况,我选择了一个调幅罪,在java中它看起来像这样:

    void genTone(){
    // fill out the array
    for (int i = 0; i < numSamples; ++i) {
        sample[i] = (binareArray.get(i))*Math.sin((2 * Math.PI - .001) * i / (sampleRate/freqOfTone));
    }


    // convert to 16 bit pcm sound array
    // assumes the sample buffer is normalised.
    int idx = 0;
    int ramp = numSamples / 20;

    for (int i = 0; i < ramp; i++) {
        // scale to maximum amplitude
        final short val = (short) ((sample[i] * 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 (int i = ramp; i < numSamples - ramp; i++) {
        // scale to maximum amplitude
        final short val = (short) ((sample[i] * 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 (int i = numSamples - ramp; i < numSamples; i++) {
        // scale to maximum amplitude
        final short val = (short) ((sample[i] * 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);
    }
}
 void playSound(){
        final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
                AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
    }

现在数据随机生成,然后从Dec转换为Bin,如下所示:

void genArray(){
    Random random = new Random();
    ArrayList<Integer> randArray = new ArrayList<>();
    binareArray = new ArrayList<>();
    for (int i = 0; i<numSamples; i++) {
        randArray.add(random.nextInt(100));
    }
    for (int i = 0; i<numSamples; i++) {
        String s = Integer.toBinaryString(randArray.get(i));
        for (String q : (s.split(""))) {
            if (q.equals("")){}
            else {
                binareArray.add(Integer.parseInt(q));
            }
        }
    }
    textView.setText(binareArray.toString());

}

所以现在我一直坚持接收和解码数据。您能否给我一个建议,如何有效地接收和解码数据?附:这是由PC麦克风(LINK

录制的音频示例

2 个答案:

答案 0 :(得分:0)

我建议您定义一个独特的开始和结束序列。添加数据之前和之后的数据。让控制序列例如是“START”和“END”。所以您发送的数据如下:

STARTyour data you want to sendEND

在Android设备上,您可以连续解码收到的音频,直到您在流上找到“START”。然后存储解码的内容,直到“END”在流上。

您收到的内容应如下所示:

noisenoisenoiseSTARTyour data you want to sendENDnoisenoisenoise

对于开始和结束序列,您必须使用无法在数据中显示的序列。如果您的数据可以是完全随机的,则必须定义一个块编码,该编码保留至少一个块以标记控制信号。将“X”作为控制块标记。您可以通过知道X之后的块是命令来将BEGIN和END定义为“XB”和“XE”。

您的数据部分不应该很长,最好多次发送。否则你需要一些纠错。然后我建议研究现有的传输协议,而不是实现自己的传输协议。

答案 1 :(得分:0)

binareArray.get(i)似乎将为i的每个值提供不同的样本。您绝对不希望以比载波频率快的速度更改样本。 老实说,我无法告诉您“斜坡”在做什么。似乎有点同步头,可以确定数据前后的范围,但该计算不会涉及数据。

就解码而言,在信号中寻找峰值,这些峰值应该是您的数据。如果您将它们与运营商同步,这将变得很容易。然后,您只需要按比例缩放标题中的最小和最大值即可。