簡體   English   中英

檢索和解碼調幅 sin

[英]Retrieving and decoding amplitude modulated sin

對於我的文憑,我需要在音頻中編碼一些數據,通過揚聲器播放,在其他 Android 手機上接收此音頻並將其解碼。 對於這種情況,我選擇了調幅 sin,在 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());

}

所以現在我被困在接收和解碼數據上。 你能給我一個建議,如何有效地接收和解碼數據? PS這是一個音頻的例子,由PC麥克風( LINK )錄制

我建議你定義一個獨特的開始和結束序列。 在您的數據之前和之后添加這些。 例如,讓控制序列為“START”和“END”。 所以你發送的數據看起來像:

STARTyour data you want to sendEND

在 Android 設備上,您會不斷解碼接收到的音頻,直到在流中找到“START”。 然后存儲解碼的內容,直到“END”出現在流中。

您收到的內容應如下所示:

noisenoisenoiseSTARTyour data you want to sendENDnoisenoisenoise

對於開始和結束序列,您必須使用不能出現在數據中的序列。 如果您的數據可以是完全隨機的,您必須定義一種塊編碼,以保留至少一個塊來標記控制信號。 為“X”控制塊標記。 通過知道 X 之后的塊是命令,您可以將 BEGIN 和 END 定義為“XB”和“XE”。

您的數據部分不應過長,最好多次發送。 否則,您將需要一些錯誤更正。 然后我會建議對現有的傳輸協議進行研究,不要實現自己的。

binareArray.get(i) 似乎會為 i 的每個值提供不同的樣本。 您絕對不希望以比運營商頻率更快的速度更改樣本。 老實說,我不知道你在用“斜坡”做什么。 這似乎是一個小的同步標頭,用於確定您的數據是否合適之前和之后的范圍,但您的數據不會參與該計算。

就解碼而言,尋找信號中的峰值,那些應該是你的數據。 如果您將它們與您的運營商同步,這將變得容易。 然后,您只需按從標題中獲得的最小值和最大值進行縮放即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM