• Disclaimer: This Vendor's Forum is a paid-for commercial area. Unlike the rest of diyAudio, the Vendor has complete control of what may or may not be posted in this forum. If you wish to discuss technical matters outside the bounds of what is permitted by the Vendor, please use the non-commercial areas of diyAudio to do so.

LADSPA filters for digital crossovers on the BBB

Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
Member
Joined 2007
Paid Member
Greetings,

Most of the discussion between page 1 and here related to difficulties using LADSPA filter plugins in alsa with MPD. It didn't work right with all players at first. I'm happy to report that the problem seems fixed. Extra special thanks to @phofman and @miero for their help! In the end, there was a configuration issue in the asound.conf file and correcting it solved all of the problems that we were up against. :D As always, please speak up if you find errors or omissions. Again, the important LADSPA filters are from here, where you can read more about their implementation. The simple delay is from Computer Music Toolkit (whose online documentation appears hacked at the moment - http://www.ladspa.org/cmt/ ). Unlike the R.Taylor setup, we are running them within ALSA, which avoids the sample rate conversions needed with other filter clients.

Below is an updated configuration for a 'generic' two way crossover using the Richard Taylor 4-pole Linkwitz-Riley high- and low-pass LADSPA filters. I have tested it to the best of my ability with my current basic setup, but more rigorous testing with decent instrumentation must wait. For now, it seems to run fine and sound fine. The good thing is that no special player configuration is needed - neither for MPD nor for squeezelite. The players' default configurations are very close to optimal. Just use the setup instructions on page 1 of this thread but copy/paste the following text to the /etc/asound.conf file, reboot, double check that the file was read using 'aplay -L' (plugins are listed at the top), and begin experimenting.



Code:
pcm.!default {
     type plug
     slave.pcm filter
}
ctl.!default {
     type hw
     card 0
}
pcm.filter {
     type ladspa
     slave.pcm eq
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
          0 {
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.2 "Output"
               input { controls [ 440 ] }   # low left [ frequency in Hz (-6dB XO point)]
          }
          1 {
               label RTlr4hipass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 440 ] }   # high left
          }
        2 {
               label RTlr4lowpass
               policy none
               input.bindings.1 "Input"
               output.bindings.3 "Output"
               input { controls [ 440 ] }   # low right
          }
        3 {
               label RTlr4hipass
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 440 ] }   # high right
          }
     }
}
pcm.eq {
     type ladspa
     slave.pcm  delay
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
        0 {
               label RTparaeq
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 0 4800 2.0 ] }   # high left [ delta dB, frequency, Q ]
          }
        1 {
               label RTparaeq
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 0 4800 2.0 ] }   # high right
          }
        2 {
               label RTparaeq
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 3 30 0.7 ] }   # low left
          }
        3 {
               label RTparaeq
               policy none
               input.bindings.3 "Input"
               output.bindings.3 "Output"
               input { controls [ 3 30 0.7 ] }   # low right
          }
            }
}

pcm.delay {
     type ladspa
     slave.pcm  speaker
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
        0 {
               label delay_5s
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 0.0 0 ] }    # high left [delay in seconds, wet/dry (0=all input, 1=all output)]
          }
        1 {
               label delay_5s
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 0.0 0 ] }   # high right - 0.001 sec. = ~ 33 cm of sound travel
          }
        2 {
               label delay_5s
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 0.0 0 ] }   # high left
          }
        3 {
               label delay_5s
               policy none
               input.bindings.3 "Input"
               output.bindings.3 "Output"
               input { controls [ 0.0 0 ] }   # high right
          }
     }
}

 pcm.speaker {
    type plug
    slave {
     pcm "t-table"
     channels 4
     rate "unchanged"
    }
}
pcm.t-table  {
    type route
    slave {
     pcm "hw:0,0"
     channels 4
    }
    ttable {
      0.0   1
      1.2   1
      2.1   1
      3.3   1
    }
}

Let me comment about each of the individual plugs in the chain. Conceptually, the 'signal' runs from top to bottom of the file. If you don't need a particular function, definitely delete its plug and correct the internal links between plugs, as described.

pcm.!default - do not edit

ctl.!default - do not edit

pcm.filter - insert your desired XO point frequency in the 'controls' box. It is set at 440Hz, which is easy to hear. I will be using mine somewhere between 120-150 Hz.

pcm.eq - many systems could use a bit of boost with low bass or perhaps the room has reflective nodes. An eq filter can address that kind of situation. [Hint: use sparingly above ~200Hz.] If you don't need them, delete the whole cpm.eq plug, and edit the slave.pcm output above in pcm.filter to connect to the next plug in line. That is, within the plug cpm.filter, the line "slave.pcm eq" might go to "slave.pcm delay" (without quotes).

pcm.delay - if your speaker or driver alignments are not optimal, you can delay the signal to any driver that, relative to the others, is located too close to the listener. In my case, my woofers will be about 33 cm in front of the midrange+tweeters. So, I will use a 0.001 second delay on the woofers, and no delay on the high frequencies. I don't know exactly how the delay filters are programmed so I will leave the two "inactive" high frequency delay filters in the chain for now. That will keep the processing more symmetrical. Later when I can set up with an oscilloscope we will see if the inactive delay filters are helping with time-keeping. Again, if you delete cpm.delay, you must link the above plug to the next in line (pcm.speaker) by editing the above slave.pcm line to "slave.pcm speaker" (no quotes).

pcm.speaker - do not edit or remove

pcm.ttable - do not remove This plug straightens out a channel alignment quirk of the BBB/Botic distro in which stereo pairs are not maintained in the channel alignments. Channels 1 (right high) and 2 (left low) are basically swapped. In each line of the table, the first number is the input channel, the second number is the output channel. [The third number is signal strength - not active here]. If you are adapting this configuration to a different system or setup, edit the ttable to correctly route the channels.


CPU draw - perfectly adequate

Using mpc/mpd, I played stereo files from 44.1 to 192kHz through the default system above. Here are the CPU numbers reported by top.

Code:
Freq.    PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND        
44.1    1027 mpd       20   0 84364  78m  26m S  13.9 15.9   1:37.01 mpd                  
48      1027 mpd       20   0 84380  78m  26m S  14.9 15.9   1:46.28 mpd                  
88.2    1027 mpd       20   0 88460  82m  26m S  27.5 16.7   1:58.75 mpd                  
96      1027 mpd       20   0 88460  82m  26m S  30.0 16.7   2:14.69 mpd                  
176.4   1027 mpd       20   0 96676  90m  26m S  55.0 18.3   2:50.14 mpd                  
192     1027 mpd       20   0 96668  90m  26m S  59.6 18.3   3:25.37 mpd

Thus, I'm optimistic that a basic three-way crossover can also be achieved with the BBB. For now, experiment - report back - enjoy!
 
Last edited:
Member
Joined 2007
Paid Member
Extending BBB/Botic function

Question for Miero:

What would it take to pipe an outside I2S source into Botic's alsa interface? Are there 3-4 pins on BBB p8 that could input into the system?

If we agree that the crossover described above is worthwhile, then it would be nice to share that filtering with other sources (than the output of music player software). Also, diverse LADSPA plugins could be used for many other functions than speaker crossovers. I assume external I2S would be easier to handle than encoded S/PDIF.

For example, with the TPA Wolfson S/PDIF transceiver, BBB could have ready access to a wide range of other audio appliances. Also, ADC has been discussed in relation to BBB, so adding an external I2S input could make Botic/BBB a great multi-function integrator for diverse audio sources. Would adding external I2S input be difficult or simple? To me, those pins on the p8 header are just begging to be used! :)
 
Last edited:
The hardware should work as I2S receiver; I've tested it using ADC from Juli@ soundcard -- http://www.diyaudio.com/forums/twis...embedded-audio-applicance-35.html#post4094282

There is only one 4 channel sound controller usable on the BBB (the CPU has two), so it would require to have matched rate/format to be able record & play at once.

And this will not work well if incomming I2S can change rate/format on the fly.

But it could be used quite well for ADC controlled by BBB, and this setup could be used as DSP processor for analog signal.
 
Member
Joined 2007
Paid Member
Thanks, that sounds encouraging. For my personal system, I would like to be able to filter the audio portion of video feeds. Critical fidelity is not the first concern. In fact, I believe all my video hardware is fixed at 48k, so setting that rate as default would make sense. I will check your comments on the other thread, give more thought, and take it from there. Thanks Miero! :)
 
Member
Joined 2007
Paid Member
francolargo: notice, delay introduced by audio processing on BBB might be issue if you want use in real-time it for video.
Yes, there is that possibility. If the delay isn't too bad, there may be delay workarounds on the video side.

However, I am unsure of my ability to get I2S into the McASP. I am now looking into pin setup but in Botic I see no xxx.dts to edit and I need to understand more about tree overlays and what activates them. And then, how to make the configured pins input correctly to McASP? I see the davinci driver is there, but I haven't looked into that yet. It's a lot for a beginner to bite off! :confused:
 
Last edited:
No need to change device tree :)

Using botic5 it should be enough to switch serializer into record mode by writing 'R' into its config slot. I've just updated missing doc on webpage.

For example (playback on data0, record on data1):
echo "IR--" > /sys/module/snd_soc_botic/parameters/serconfig
 
Member
Joined 2007
Paid Member
That sounds great, but I should study more before I attempt this! :eek:

I think the master clock input to the WM8804 can come from Cronus, which should align the other I2S clocks on the spdif -> I2S transceiver. But then, Dout from WM8804 - will it go 'backwards' through the isolator and is P9_42 configured for input? I am reading the Derek Molloy book on the BBB and am perhaps overly cautious about GPIO connections.
 
Member
Joined 2007
Paid Member
3-way crossover in alsa seems viable on BBB

Curiosity got the better of me, so I tried running a 3-way alsa crossover configuration file even though my system doesn't have DACs on all the needed outputs. Because of this, there was some 'channel-seeking' in the output (not nice), but I just wanted to see how the BBB CPU managed. While playing a 192kHz .wav file using mpc/mpd, CPU demand was about 70%. Very manageable and encouraging. Here is the asound.conf file if you want to experiment. Remember that channel alignments may need adjustment using the ttable - suggest using 'speaker-test -c2' and listen for the frequencies on each output channel. If things go wrong, a hard reboot is suggested after asound.conf edits.

Code:
pcm.!default {
     type plug
     slave.pcm filter
}
ctl.!default {
     type hw
     card 0
}
pcm.filter {
     type ladspa
     slave.pcm delay
     path "/usr/lib/ladspa"
     channels 6               # high = channels 0,1; low = channels 2,3; mid = channels 4,5
     plugins
     {
          0 {
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.2 "Output"
               input { controls [ 250 ] }   # left low [frequency (Hz)]
          }
          1 {
               label RTlr4hipass
               policy none
               input.bindings.0 "Input"
               output.bindings.4 "Output"
               input { controls [ 250 ] }   # left mid bottom
          }
        2 {
               label RTlr4lowpass
               policy none
               input.bindings.1 "Input"
               output.bindings.3 "Output"
               input { controls [ 250 ] }    # right low
          }
        3 {
               label RTlr4hipass
               policy none
               input.bindings.1 "Input"
               output.bindings.5 "Output"
               input { controls [ 250 ] }    # right mid bottom
          }
        4 {
               label RTlr4hipass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 4000 ] }    # left high
          }
        5 {
               label RTlr4lowpass
               policy none
               input.bindings.4 "Input"
               output.bindings.4 "Output"
               input { controls [ 4000 ] }    # left mid top
          }
        6 {
               label RTlr4hipass
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 4000 ] }    # right high
          }
        7 {
               label RTlr4lowpass
               policy none
               input.bindings.5 "Input"
               output.bindings.5 "Output"
               input { controls [ 4000 ] }    # right mid top
          }
     }
}
pcm.delay {
     type ladspa
     slave.pcm  speaker
     path "/usr/lib/ladspa"
     channels 6
     plugins
     {
        0 {
               label delay_5s
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 0.0 1 ] }    # low channels only [delay in seconds, wet/dry (0=all input, 1=all output)]
          }
        1 {
               label delay_5s
               policy none
               input.bindings.3 "Input"
               output.bindings.3 "Output"
               input { controls [ 0.0 1 ] }
          }
     }
}
pcm.speaker {
    type plug
    slave {
     pcm "t-table"
     channels 6
     rate "unchanged"
    }
}
pcm.t-table  {
    type route
    slave {
     pcm "hw:0,0"
     channels 6
    }
    ttable {
      0.0   1
      1.1   1
      2.2   1
      3.3   1
      4.4   1
      5.5   1
    }
}

pcm.plughw.slave.rate = "unchanged";

If you try this, please share your results and impressions! ;)
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.