Custom File Import (Example: *.wav file from GNU Radio)
Quote from DevSF on 15/07/2021, 09:54By using the Script block you can import data files into the RTSA Suite with any data format.
In this example especially, I use a RIFF WAVE file generated by the Wave Sink block of the GNU Radio toolbox.
Following code snippet will read an IQ data file in the Riff Wave file format (data as PCM values, 8,16 or 32bit are supported) and send this data as IQ Stream packet into the RTSA Suite for further analysis:
import { File } from "fs.js"
import { DSPStream } from "dspstream.js"File.read("E:/testData/Sinus_F-1MHz_Fs-10MHz_16Bit.wav").then(d => {
let chunkID = d.slice(0,4);
let chunkSize = 8 + new DataView( d, 4).getUint32(0, true);
let riffType = d.slice(8,12);if(UTF8.decode(chunkID) != "RIFF" || UTF8.decode(riffType) != "WAVE") {
console.log("Format is not supported");
return;
}let headerSig = d.slice(12,16);
let headerLen = new DataView(d, 16).getUint32(0, true);let formatTag = new DataView(d, 20).getUint16(0, true);
let channels = new DataView(d, 22).getUint16(0, true);
let sampleRate = new DataView(d, 24).getUint32(0, true);
let bytesPerSec = new DataView(d, 28).getUint16(0, true);
let blockAlign = new DataView(d, 32).getUint16(0, true);
let bitsPerSample = new DataView(d, 34).getUint16(0, true);let subChunkID = d.slice(36,40);
let subChunkLen = new DataView(d, 40).getUint32(0, true);if(formatTag != 1 || UTF8.decode(headerSig) != "fmt " || UTF8.decode(subChunkID) != "data"){
console.log("Format is not supported. Only PCM values are supported");
return;
}var dataView = new DataView(d, 44, subChunkLen);
let sampleCount = subChunkLen/channels/(bitsPerSample/8);console.log("--------------");
console.log("Chunk ID:" + UTF8.decode(chunkID));
console.log("Chunk Size:" + chunkSize);
console.log("Riff Type:" +UTF8.decode(riffType));
console.log("Header Sig:" +UTF8.decode(headerSig));
console.log("Header Len:" + headerLen);
console.log("Data Format:" + formatTag);
console.log("Channels:" + channels);
console.log("SampleRate:" + sampleRate);
console.log("Byte Rate:" + bytesPerSec);
console.log("Block Align:" + blockAlign);
console.log("Bits per Sample:" + bitsPerSample);
console.log("Subchunk ID:" + UTF8.decode(subChunkID));
console.log("Subchunk Len:" + subChunkLen);
console.log("Sample Count:" + sampleCount);var float32View = new Float32Array(sampleCount*channels);
var byteIndex = 0;
var x;if (bitsPerSample == 32) {
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt32(byteIndex, true);
float32View[i] = x < 0 ? x/2147483648 : x/2147483647;byteIndex += 4;
}
}
else if(bitsPerSample == 16){
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt16(byteIndex, true);
float32View[i] = x < 0 ? x/32768 : x/32767;byteIndex += 2;
}
}
else if (bitsPerSample == 8) {
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt8(i, true);
float32View[i] = x < 0 ? x/128 : x/127;
}
}
else
{
console.log("Bits per sample are not suported! 8,16 or 32 bit per Sample are supported");
return;
}var packet = {
depth: 1,
payload: "iq",
unit: "volt",
minValue: -1,
maxValue: 1,
startFrequency: -sampleRate/2,
endFrequency: +sampleRate/2,
stepFrequency: sampleRate,
samples: float32View,
startTime: 0,
endTime: sampleCount/sampleRate
}DSPStream.sendPacket(0, packet);
console.log("OK!");
});
For bigger input Files(>50MB) you may need to increase the Heap Memory Size in the Interpreter settings of the Script block. You will get an error running the Script block if the heap memory is exceeded.
For much larger files you may need to read the file in chunks and implement the asynchronous file read methods as described in the JSIQA documentation (https://v6-forum.aaronia.de/forum/topic/rtsa-suite-pro-java-script-support/)
Attached you can find the mission and a small sample file.
By using the Script block you can import data files into the RTSA Suite with any data format.
In this example especially, I use a RIFF WAVE file generated by the Wave Sink block of the GNU Radio toolbox.
Following code snippet will read an IQ data file in the Riff Wave file format (data as PCM values, 8,16 or 32bit are supported) and send this data as IQ Stream packet into the RTSA Suite for further analysis:
import { File } from "fs.js"
import { DSPStream } from "dspstream.js"File.read("E:/testData/Sinus_F-1MHz_Fs-10MHz_16Bit.wav").then(d => {
let chunkID = d.slice(0,4);
let chunkSize = 8 + new DataView( d, 4).getUint32(0, true);
let riffType = d.slice(8,12);if(UTF8.decode(chunkID) != "RIFF" || UTF8.decode(riffType) != "WAVE") {
console.log("Format is not supported");
return;
}let headerSig = d.slice(12,16);
let headerLen = new DataView(d, 16).getUint32(0, true);let formatTag = new DataView(d, 20).getUint16(0, true);
let channels = new DataView(d, 22).getUint16(0, true);
let sampleRate = new DataView(d, 24).getUint32(0, true);
let bytesPerSec = new DataView(d, 28).getUint16(0, true);
let blockAlign = new DataView(d, 32).getUint16(0, true);
let bitsPerSample = new DataView(d, 34).getUint16(0, true);let subChunkID = d.slice(36,40);
let subChunkLen = new DataView(d, 40).getUint32(0, true);if(formatTag != 1 || UTF8.decode(headerSig) != "fmt " || UTF8.decode(subChunkID) != "data"){
console.log("Format is not supported. Only PCM values are supported");
return;
}var dataView = new DataView(d, 44, subChunkLen);
let sampleCount = subChunkLen/channels/(bitsPerSample/8);console.log("--------------");
console.log("Chunk ID:" + UTF8.decode(chunkID));
console.log("Chunk Size:" + chunkSize);
console.log("Riff Type:" +UTF8.decode(riffType));
console.log("Header Sig:" +UTF8.decode(headerSig));
console.log("Header Len:" + headerLen);
console.log("Data Format:" + formatTag);
console.log("Channels:" + channels);
console.log("SampleRate:" + sampleRate);
console.log("Byte Rate:" + bytesPerSec);
console.log("Block Align:" + blockAlign);
console.log("Bits per Sample:" + bitsPerSample);
console.log("Subchunk ID:" + UTF8.decode(subChunkID));
console.log("Subchunk Len:" + subChunkLen);
console.log("Sample Count:" + sampleCount);var float32View = new Float32Array(sampleCount*channels);
var byteIndex = 0;
var x;if (bitsPerSample == 32) {
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt32(byteIndex, true);
float32View[i] = x < 0 ? x/2147483648 : x/2147483647;byteIndex += 4;
}
}
else if(bitsPerSample == 16){
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt16(byteIndex, true);
float32View[i] = x < 0 ? x/32768 : x/32767;byteIndex += 2;
}
}
else if (bitsPerSample == 8) {
for(let i = 0; i < sampleCount*channels; i++){
x = dataView.getInt8(i, true);
float32View[i] = x < 0 ? x/128 : x/127;
}
}
else
{
console.log("Bits per sample are not suported! 8,16 or 32 bit per Sample are supported");
return;
}var packet = {
depth: 1,
payload: "iq",
unit: "volt",
minValue: -1,
maxValue: 1,
startFrequency: -sampleRate/2,
endFrequency: +sampleRate/2,
stepFrequency: sampleRate,
samples: float32View,
startTime: 0,
endTime: sampleCount/sampleRate
}DSPStream.sendPacket(0, packet);
console.log("OK!");
});
For bigger input Files(>50MB) you may need to increase the Heap Memory Size in the Interpreter settings of the Script block. You will get an error running the Script block if the heap memory is exceeded.
For much larger files you may need to read the file in chunks and implement the asynchronous file read methods as described in the JSIQA documentation (https://v6-forum.aaronia.de/forum/topic/rtsa-suite-pro-java-script-support/)
Attached you can find the mission and a small sample file.
Uploaded files:Quote from SpectraNet on 16/07/2021, 08:40Thank you for this--this is very helpful. I was able to get the 1 MHz sample wav file to work exactly as shown above. I'm using 1411 kbps, 16 bit *.wav files that are baseband audio, so can play using the windows player app. However, I get the not "PCM format" error, so will try other audio converters to convert to the proper format, if possible. -Jeff
Thank you for this--this is very helpful. I was able to get the 1 MHz sample wav file to work exactly as shown above. I'm using 1411 kbps, 16 bit *.wav files that are baseband audio, so can play using the windows player app. However, I get the not "PCM format" error, so will try other audio converters to convert to the proper format, if possible. -Jeff
Quote from DevSF on 17/07/2021, 08:14The open source tool Audacity should do the job. In the export dialog you can select signed PCM 16bit as output format.
Or you adapt the Script block code.
The open source tool Audacity should do the job. In the export dialog you can select signed PCM 16bit as output format.
Or you adapt the Script block code.
Quote from DevSF on 19/07/2023, 11:54Hi,
this is strange I was quiet sure it was attached.
Anyway I still found it on disk (see attached), also it should be quiet easy to rebuild the mission from scratch
Hi,
this is strange I was quiet sure it was attached.
Anyway I still found it on disk (see attached), also it should be quiet easy to rebuild the mission from scratch
Uploaded files: