Search code examples
javascriptnode.jsparsingfrequency

How can I parse a .frd file with Javascript?


A .frd file is a type of multi-column numeric data table used for storing information about the frequency response of speakers. A .frd file looks something like this when opened in a text editor:

2210.4492       89.1    -157.7
2216.3086       88.99   -157.7
2222.168        88.88   -157.6
2228.0273       88.77   -157.4

Using javascript, is there a way that I can parse this data in order to return each column separately?

For example, from the .frd file above, I would need to return the values like so:

var column1 = [2210.4492, 2216.3086, 2222.168, 2228.0273];

var column2 = [89.1, 88.99, 88.88, 88.77];

var column3 = [-157.7, -157.7, -157.6, -157.4];

I'm not exactly sure where to begin in trying to achieve this, so any step in the right direction would be helpful!


Solution

  • I found the following description of the FRD file format and I will follow it.

    Let's assume that the content of your .frd file is in the variable called content (the following example is for Node.js):

    const fs = require('fs');
    const content = fs.readFileSync('./input.frd').toString();
    

    Now if content has your FRD data, it means it's a set of lines, each line contains exactly three numbers: a frequency (Hz), a level (dB), and a phase (degrees). To split your content into lines, we can just literally split it:

    const lines = content.split(/\r?\n/);
    

    (normally, splitting just by '\n' would've worked, but let's explicitly support Windows-style line breaks \r\n just in case. The /\r?\n/ is a regular expression that says "maybe \r, then \n")

    To parse each line into three numbers, we can do this:

    const values = line.split(/\s+/);
    

    If the file can contain empty lines, it may make sense to double check that the line has exactly three values:

    if (values.length !== 3) {
      // skip this line
    }
    

    Given that we have three values in values, as strings, we can assign the corresponding variables:

    const [frequency, level, phase] = values.map(value => Number(value));
    

    (.map converts all the values in values from strings to Number - let's do this to make sure we store the correct type).

    Now putting all those pieces together:

    const fs = require('fs');
    const content = fs.readFileSync('./input.frd').toString();
    
    const frequencies = [];
    const levels = [];
    const phases = [];
    
    const lines = content.split(/\r?\n/);
    for (const line of lines) {
      const values = line.split(/\s+/);
      if (values.length !== 3) {
        continue;
      }
      const [frequency, level, phase] = values.map(value => Number(value));
      frequencies.push(frequency);
      levels.push(level);
      phases.push(phase);
    }
    
    console.log(frequencies);
    console.log(levels);
    console.log(phases);
    

    The main code (the one that works with content) will also work in browser, not just in Node.js, if you need that.

    This code can be written in a tons of different ways, but I tried to make it easier to explain so did something very straightforward.

    To use it in Node.js (if your JavaScript file is called index.js):

    $ cat input.frd 
    2210.4492       89.1    -157.7
    2216.3086       88.99   -157.7
    2222.168        88.88   -157.6
    2228.0273       88.77   -157.4
    
    $ node index.js 
    [ 2210.4492, 2216.3086, 2222.168, 2228.0273 ]
    [ 89.1, 88.99, 88.88, 88.77 ]
    [ -157.7, -157.7, -157.6, -157.4 ]