• 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
Not open for further replies.
@francolargo. I took a look at the setup you have on github (thanks for that BTW!). I tried using that with and without sudo, still didn't work, but I finally got a useful error message - apparently I forgot to export the ladspa plugin directory (rookie mistake). Now it works!!!! I got the channels setup and everything 😀. I'll post some more details shortly, for now my kids are *forcing* me to play minecraft with them 0_o
Thanks for your help!


Sent from my iPhone using Tapatalk
 
@francolargo. I took a look at the setup you have on github (thanks for that BTW!). I tried using that with and without sudo, still didn't work, but I finally got a useful error message - apparently I forgot to export the ladspa plugin directory (rookie mistake). Now it works!!!! I got the channels setup and everything 😀. I'll post some more details shortly, for now my kids are *forcing* me to play minecraft with them 0_o
Thanks for your help!


Sent from my iPhone using Tapatalk

Most excellent! What OS on the RPi? That most recent asound.conf does not use the delay or any EQ - you see that the crossover plugin routes directly to the pcm.speaker plug.

When you are running the crossover, I'd be curious to know what kind of CPU it is drawing using 'top' in a separate window...

It would be nice to know if Charlie Laub's filter set works in ALSA on your rig. ...you may have to go back to ecasound. But glad to hear of your success and any updates re: the RPi will be of interest.

Best,

Frank
 
Last edited:
Most excellent! What OS on the RPi? That most recent asound.conf does not use the delay or any EQ - you see that the crossover plugin routes directly to the pcm.speaker plug.

When you are running the crossover, I'd be curious to know what kind of CPU it is drawing using 'top' in a separate window...

It would be nice to know if Charlie Laub's filter set works in ALSA on your rig. ...you may have to go back to ecasound. But glad to hear of your success and any updates re: the RPi will be of interest.

Best,

Frank


I'm using raspbian jessie built from the lite image, with a custom kernel I compiled (kustom kompiled kernel?)

I'll try out top in a bit. I still have to connect mpd


Sent from my iPhone using Tapatalk
 
Okay, as promised, my .asoundrc file
Code:
pcm.!default {
     type plug
     slave.pcm filter1
}
ctl.!default {
     type hw
     card 0
}
pcm.filter1 {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"    
     channels 8
     plugins
     {
          0 {
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.2 "Output"
               input { controls [ 200 ] }   # [frequency (Hz)]
          }
          1 {
               id 9007
               policy none
               input.bindings.0 "Input"
               output.bindings.4 "Output"
               input { controls [ 4200 ] }
          }
        2 {
               label RTlr4lowpass
               policy none
               input.bindings.1 "Input"
               output.bindings.3 "Output"
               input { controls [ 200 ] }
          }
        3 {
               id 9007
               policy none
               input.bindings.1 "Input"
               output.bindings.5 "Output"
               input { controls [ 4200 ] }
          }
        4 {
               label RTlr4hipass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 200 ] }
          }
        5 {
               label RTlr4hipass
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 200 ] }
          }
        6 {
               id 9006
               policy none
               input.bindings.0"Input"
               output.bindings.6 "Output"
               input { controls [ 4200 ] }
          }
        7 {
               id 9006
               policy none
               input.bindings.1 "Input"
               output.bindings.7 "Output"
               input { controls [ 4200 ] }
          }

     }
}
pcm.delay {
     type ladspa
     slave.pcm  speaker
     path "/usr/lib/ladspa" 
     channels 8
     plugins
     {
        0 {
               label delay_5s
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 0.012 1 ] }    # [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.012 1 ] }
          }
     }
}
pcm.speaker {
    type plug
    slave {
     pcm "t-table"  
     channels 8
     rate "unchanged"
    }
}
pcm.t-table  {
    type route
    slave {
     pcm "hw:0,0"
     channels 8
    }
    ttable {
      0.0   0  # audio = left woofer channel = left front
      1.1   0  
      2.0   1  #left bass this gives me the low filter for left woofer onto channel 0, left front
      3.7   1  #right bass  = SBR
      4.6   0.25  #left tweeter = SBL (audio says left woofer though)
      5.5   0.25  #right tweeter = Surr Right (audio says right woofer)
      6.4   0.75  #left mid = surr left (audio says left woofer)
      7.3   0.75  #right mid = center (audio says right woofer)
    }
}

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

and top
Code:
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                         
19576 pi        20   0  253500  67184  18316 S 127.5  7.1  10:44.00 nodejs                                                                          
   44 root       1 -19       0      0      0 S   0.7  0.0   0:02.67 VCHIQ-0                                                                         
   45 root       1 -19       0      0      0 S   0.7  0.0   0:02.11 VCHIQr-0                                                                        
 1041 root       0 -20       0      0      0 S   0.7  0.0   0:01.46 kworker/0:1H                                                                    
    7 root      20   0       0      0      0 R   0.3  0.0   0:02.30 rcu_sched                                                                       
 3108 root      20   0       0      0      0 S   0.3  0.0   0:05.30 kworker/u8:2                                                                    
19980 pi        20   0   11476   2996   2388 S   0.3  0.3   0:00.42 sshd                                                                            
19993 pi        20   0    5112   2452   2088 R   0.3  0.3   0:01.65 top                                                                             
20568 root      20   0       0      0      0 S   0.3  0.0   0:00.55 kworker/u8:3                                                                    
    1 root      20   0    5524   3888   2724 S   0.0  0.4   0:05.48 systemd                                                                         
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd                                                                        
    3 root      20   0       0      0      0 S   0.0  0.0   0:00.30 ksoftirqd/0                                                                     
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                                    
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh                                                                          
    9 root      rt   0       0      0      0 S   0.0  0.0   0:00.04 migration/0                                                                     
   10 root      rt   0       0      0      0 S   0.0  0.0   0:00.04 migration/1                                                                     
   11 root      20   0       0      0      0 S   0.0  0.0   0:00.08 ksoftirqd/1                                                                     
   13 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H                                                                    
   14 root      rt   0       0      0      0 S   0.0  0.0   0:00.07 migration/2                                                                     
   15 root      20   0       0      0      0 S   0.0  0.0   0:00.04 ksoftirqd/2                                                                     
   17 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/2:0H                                                                    
   18 root      rt   0       0      0      0 S   0.0  0.0   0:00.07 migration/3                                                                     
   19 root      20   0       0      0      0 S   0.0  0.0   0:00.08 ksoftirqd/3                                                                     
   21 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/3:0H                                                                    
   22 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 khelper                                                                         
   23 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kdevtmpfs                                                                       
   24 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns                                                                           
   25 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 perf                                                                            
   26 root      20   0       0      0      0 S   0.0  0.0   0:00.00 khungtaskd                                                                      
   27 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 writeback                                                                       
   28 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 crypto                                                                          
   29 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset                                                                          
   30 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kblockd

One question: how do you adjust the level of drivers? My tweeters are way too hot.
Second question: how do you daisy chain filters together? My next trick is to figure out the levels, then phase tweaks, make sure the crossover points are optimized, and EQ... phew ;
But it's working. By gawd I have 6 channel audio being piped out from a raspberry pi over HDMI!!
 
and top
Code:
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                         
19576 pi        20   0  253500  67184  18316 S 127.5  7.1  10:44.00 nodejs

Clearly, top is calibrated to one core! But 65% CPU use gives you room to work. If that was MPD doing the playing, then the system would seem very viable, no?

One question: how do you adjust the level of drivers? My tweeters are way too hot.

I personally am using I2S out of the BBB, which I then play via 3 separately controlled DACs for tweeters, mids, and woofers. That control is via I2C between the DACs and the BBB. I have a separate 'control' thread discussing my experiences: http://www.diyaudio.com/forums/twisted-pear/281776-control-bbb-based-audio-appliances.html. The control software should work on a RPi, though with very different scripts. My tweeters run hot as well, so the 'trim' functions on my remote control get used all the time.

How should you control driver volume? Maybe start by using the 'contribution factor' in the t-table (after the space). Start by replacing the 1 with, oh, 0.6. That should be noticeable. If that seems to work, then tweak to your liking. That would be a start, though not the best theoretical solution. The way I do it uses 48 bit precision in the DAC itself - about as clean as possible. I'm pretty sure there are LADSPA filters that will also attenuate - check some of the filter list links in the first few posts of this thread. If you went to ecasound I believe there are attenuators available there too. You could also put an L-pad on each tweeter and do it analogue.
Second question: how do you daisy chain filters together? My next trick is to figure out the levels, then phase tweaks, make sure the crossover points are optimized, and EQ... phew ;
But it's working. By gawd I have 6 channel audio being piped out from a raspberry pi over HDMI!!

You have that indeed, and you are on the cutting edge, amigo! Good work! 😀

With the R Taylor filter set you don't have quite the flexibility of other sets. I use the 2-pole L-R filter between mid and tweeter because I hear fewer phase effects, especially in the form of clearer positional detail of those higher frequencies. My mids play very well up and over 4kHz, so crossing that high (~4000 Hz) keeps female voices 'together'. 'Daisy chaining' is done by subsequent plugs, after the filter roll-offs. For example, you have a 'delay' plug that is currently doing nothing. You could also have an EQ plug, or a volume plug. Just manipulate each channel as needed and feed each plug into the next. See the 'generic' ALSA example earlier in the thread, where 'slave.pcm XXX' specifies the next plug in line (which would start with 'pcm.XXX'). However, you don't have THAT much CPU overhead left. So choose your tweaks wisely. With my highly resolving DACs, amps, and speakers, I like fewer tweaks. The simpler the chain is, the better it sounds. Maybe with FIR filters one could be more manipulative without penalty. But none of the SOC minicomputers have the starch to run those. Play with it, and try out various solutions to your perceived faults. Within the RPi you can script changes or adjustments fairly easily using bash or python. ...and then control them from your phone using NetIO!

Since you are the first to bridge these methods over the the RPi, please feel free to keep reporting back as a 'logbook' for the benefit of others.

Best,

Frank
 
Last edited:
Sorry - just noticed that your t-table is attenuating to 0.25 for the tweeters and 0.75 for the midrange channels. Is that working for you?

Also, if you keep the delay plug but don't currently use it, might as well change the delay period from 12ms to 0.0 seconds.
 
Sorry - just noticed that your t-table is attenuating to 0.25 for the tweeters and 0.75 for the midrange channels. Is that working for you?

Also, if you keep the delay plug but don't currently use it, might as well change the delay period from 12ms to 0.0 seconds.

using 0-1 scaling does work... but it's a bit rough where what I want is DB increments. I can make it work through trial and error if I need to, though.
 
Sorry - just noticed that your t-table is attenuating to 0.25 for the tweeters and 0.75 for the midrange channels. Is that working for you?

Also, if you keep the delay plug but don't currently use it, might as well change the delay period from 12ms to 0.0 seconds.
Well, apparently the 0-1 scalar on the t.table is blending or something weird. 0=off, 1=on, 0.5 blending two channels together... whatever.

Anyhoo, thought you might be interested to know I got @CharlieLaub 's plugins to work in asoundrc.
Also @francolargo, I found a bug in your asoundrc file, you aren't sending the mids their highpass filter, just the lowpass. But maybe that's just my bug from my edit?

Anyway, here's how you can get Charlie's plugins working through native alsa. I'm too tired tonight to fiddle with it anymore.

Code:
#asound rc new version jrubinstein - experimental with charlies plugin
pcm.!default {
     type plug
     slave.pcm filter1
}
ctl.!default {
     type hw
     card 0
}
pcm.filter1 {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"    
     channels 8
     plugins
     {
          0 {
               label ACDf #lowpass for woofer output to channel2
               policy none
               input.bindings.0 "Input"
               output.bindings.2 "Output"
               input { controls [21 1 0 300 0.7] }   # [filter type polarity dbgain frequency q] 
          }
        1 {
               label ACDf #highpass for tweeter, output to channel4
               policy none
               input.bindings.0 "Input"
               output.bindings.4 "Output"
               input { controls [22 1 -11 3000 0.7] } #2nd order highpass at 3000 hz 
          }
        2 {
               label ACDf #lowpass for woofer output to channel3
               policy none
               input.bindings.1 "Input"
               output.bindings.3 "Output"
               input { controls [21 1 0 300 0.7] } #2nd order lowpass at 300hz not working
          }
        3 {
               label ACDf #highpass for tweeter output to channel5
               policy none
               input.bindings.1 "Input"
               output.bindings.5 "Output"
               input { controls [22 1 -11 3000 0.7] } #2nd order highpass at 3000 hz 
          }
        4 {
               label ACDf #highpass for mid output to channel0 
               policy none
               input.bindings.0 "Input"
               output.bindings.6 "Output"
               input { controls [22 1 -6 300 0.7] } # 2nd order highpass at 300 hz 
          }
        5 {
               label ACDf  #highpass for mid output to channel 1
               policy none
               input.bindings.1 "Input"
               output.bindings.7 "Output"
               input { controls [22 1 -6 300 0.7] } #2nd order highpass at 300 hz 
          }
        6 {
               label ACDf #lowpass for mid output to channel 6
               policy none
               input.bindings.0"Input"
               output.bindings.6 "Output"
               input { controls [21 1 0 3000 0.7] } #2nd order lowpass at 3000 hz 
          }
        7 {
               label ACDf #lowpass for mid output to channel 7
               policy none
               input.bindings.1 "Input"
               output.bindings.7 "Output"
               input { controls [21 1 0 3000 0.7] } #2nd order lowpass at 3000 hz 
          }

     }
}
pcm.delay {
     type ladspa
     slave.pcm  speaker
     path "/usr/lib/ladspa" 
     channels 8
     plugins
     {
        0 {
               label delay_5s
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 0.012 1 ] }    # [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.012 1 ] }
          }
     }
}
pcm.speaker {
    type plug
    slave {
     pcm "t-table"  
     channels 8
     rate "unchanged"
    }
}
pcm.t-table  {
    type route
    slave {
     pcm "hw:0,0"
     channels 8
    }
    ttable {
      0.0   0  # audio = left woofer channel = left front
      1.1   0
      2.0   1  #left bass this gives me the low filter for left woofer onto channel 0
      3.7   1  #right bass  = SBR
      4.6   1  #left tweeter = SBL (audio says left woofer though)
      5.5   1  #right tweeter = Surr Right (audio says right woofer)
      6.4   1  #left mid = surr left (audio says left woofer)
      7.3   1  #right mid = center (audio says right woofer)
    }
}

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

I just roughed in the levels by ear. Next steps are to set up proper crossover slopes and gaps, set the levels, then eq. Phew!

Any thoughts you may have on that subject are welcome 😀

Cheers!
JR
 
top output, in case anyone wants to know the diffs between the standard and RT plugins and running Charlie's

Code:
 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                           
12281 pi        20   0  282424  56272  18012 S 115.5  5.9   3:17.52 nodejs                                                                            
   44 root       1 -19       0      0      0 S   0.7  0.0   0:06.29 VCHIQ-0                                                                           
13375 pi        20   0    5112   2476   2112 R   0.7  0.3   0:00.15 top                                                                               
   45 root       1 -19       0      0      0 S   0.3  0.0   0:07.48 VCHIQr-0                                                                          
 1283 root       0 -20       0      0      0 S   0.3  0.0   0:03.26 kworker/0:1H                                                                      
 6139 root      20   0       0      0      0 S   0.3  0.0   0:01.23 kworker/u8:3                                                                      
12051 root      20   0       0      0      0 S   0.3  0.0   0:00.59 kworker/u8:2                                                                      
    1 root      20   0    5524   3896   2732 S   0.0  0.4   0:05.93 systemd                                                                           
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.01 kthreadd                                                                          
    3 root      20   0       0      0      0 S   0.0  0.0   0:00.72 ksoftirqd/0                                                                       
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                                      
    7 root      20   0       0      0      0 S   0.0  0.0   0:04.36 rcu_sched                                                                         
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh                                                                            
    9 root      rt   0       0      0      0 S   0.0  0.0   0:00.15 migration/0                                                                       
   10 root      rt   0       0      0      0 S   0.0  0.0   0:00.13 migration/1                                                                       
   11 root      20   0       0      0      0 S   0.0  0.0   0:00.16 ksoftirqd/1                                                                       
   13 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H                                                                      
   14 root      rt   0       0      0      0 S   0.0  0.0   0:00.23 migration/2                                                                       
   15 root      20   0       0      0      0 S   0.0  0.0   0:00.12 ksoftirqd/2                                                                       
   17 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/2:0H                                                                      
   18 root      rt   0       0      0      0 S   0.0  0.0   0:00.27 migration/3                                                                       
   19 root      20   0       0      0      0 S   0.0  0.0   0:00.14 ksoftirqd/3                                                                       
   21 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/3:0H                                                                      
   22 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 khelper                                                                           
   23 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kdevtmpfs                                                                         
   24 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns                                                                             
   25 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 perf                                                                              
   26 root      20   0       0      0      0 S   0.0  0.0   0:00.01 khungtaskd                                                                        
   27 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 writeback                                                                         
   28 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 crypto                                                                            
   29 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset                                                                            
   30 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kblockd                                                                           
   32 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 rpciod
 
Well, apparently the 0-1 scalar on the t.table is blending or something weird. 0=off, 1=on, 0.5 blending two channels together... whatever.

Yes, the 0-1 scalar can blend channels, as mentioned in post #117. Here is a different solution for balancing channels that might be better at avoiding pollution - test and evaluate in your system. Use a LADSPA amplifier filter to do the attenuation. The Computer Music Toolkit suite contains amplifier filters #1067 and 1068 that can do it, though there should be others and they may sound different. You can import the CMT using apt-get, if you haven't already.

I renamed the 'delay' plug to 'balance', pointed the 'filter1' plug to it (instead of 'speaker') and pointed the new 'balance' plug to 'speaker'. The following attenuated my own tweeters very effectively. As mentioned above, I won't be using this method because my DACs can do the job with 48 bit precision, but it is nice to see that this LADSPA option is viable. Probably the precision is the same as the attenuation function built into ecasound.
Code:
pcm.balance {
     type ladspa
     slave.pcm  speaker
     path "/usr/lib/ladspa"
     channels 8
     plugins
     {
        0 {
               label amp_mono
               policy none
               input.bindings.4 "Input"
               output.bindings.4 "Output"
               input { controls [ 0.4 ] }    # (0 to ..., 1 is default)
          }
        1 {
               label amp_mono
               policy none
               input.bindings.5 "Input"
               output.bindings.5 "Output"
               input { controls [ 0.4 ] }
          }
     }
}
Anyhoo, thought you might be interested to know I got @CharlieLaub 's plugins to work in asoundrc.
Also @francolargo, I found a bug in your asoundrc file, you aren't sending the mids their highpass filter, just the lowpass. But maybe that's just my bug from my edit?

I have found that ALSA can act 'wonky'! For example, for the midrange one would think that high passing input channel 0 to output channel 6, then low passing channel 6 to 6 would be the same as high passing channel 0 to 0 and then low passing 0 to 6. But for me it only works the way I have it - but it does work for me.

I'm delighted that you (@jrubins) have the ACDf filters working in Jessie! When I last tried using them I got nothing but segmentation faults. It made no sense, but the Richard Taylor filters were working so I forged ahead using those. I thought perhaps something in the ALSA LADSPA handler wasn't quite right. Based on your success, I was thinking that perhaps upgrading to Jessie (not trivial with the Botic kernel) might just crack that problem. But for the heck of it, without upgrading Wheezy, I just copied and pasted the text for your left woofer lowpass filter into my asound.conf file. And??? ...segmentation faults again???

The little sucker ran! 😕😀😕 Maybe I can't type, but maybe ALSA is 'wonky'! This kind of experience reinforces the three objectives of this thread as stated in the first post! So I will be playing with the ACDf set in the next few days. I'll report results here.

I just roughed in the levels by ear. Next steps are to set up proper crossover slopes and gaps, set the levels, then eq. Phew!

Any thoughts you may have on that subject are welcome 😀

Cheers!
JR

It will be very interesting to see how much work you can extract from the RPi! If, in fact, the ACDf filters are now completely functional on the BBB, then there will be lots of interesting cross comparisons. So keeping up the dialogue will probably be worthwhile. I think Charlie will be glad to hear that the ACDf filters are working in ALSA plugins. Since you are the one to have cracked that, at some point why not post a "success" notice (plus a link to this discussion) on Charlie's filter thread?

I also noticed a link to this Alsa implementation thread in a comment on Richard Taylor's blog. He expressed skepticism regarding the focus on 'bit-perfect' signals. As a buzzword 'bit-perfect' has a checkered past with many interpretations. Now with linux renderers like the BBB, RPi, etc., - very simple processors with customizable clocks - the jury can become more definitive on the role of clocking/resampling. What do I hear when PCM is synthesized under control of a 'native sampling frequency' clock? Exclusive of the filtering in ALSA, bad recordings sound even worse, good recordings clearly sound even better. My immediate objective here is to make the crossovers sound as transparent as the unfiltered DAC output that I can enjoy via headphones. But I'm not a bit-perfect evangelist. At some time in the future I would like to try resampling in HQPlayer. For now, ONWARD! 😀
 
Last edited:
I have found that ALSA can act 'wonky'! For example, for the midrange one would think that high passing input channel 0 to output channel 6, then low passing channel 6 to 6 would be the same as high passing channel 0 to 0 and then low passing 0 to 6. But for me it only works the way I have it - but it does work for me.
This may be the implementation using Richard's plugins... no big deal. I checked mine by switching each filter on/off independently, so that works for me. It may be an implementation detail, so it's good for people to be aware.

I'm delighted that you (@jrubins) have the ACDf filters working in Jessie! When I last tried using them I got nothing but segmentation faults. It made no sense, but the Richard Taylor filters were working so I forged ahead using those. I thought perhaps something in the ALSA LADSPA handler wasn't quite right. Based on your success, I was thinking that perhaps upgrading to Jessie (not trivial with the Botic kernel) might just crack that problem. But for the heck of it, without upgrading Wheezy, I just copied and pasted the text for your left woofer lowpass filter into my asound.conf file. And??? ...segmentation faults again???

The little sucker ran! 😕😕😕 Maybe I can't type, but maybe ALSA is 'wonky'! This kind of experience reinforces the three objectives of this thread as stated in the first post! So I will be playing with the ACDf set in the next few days. I'll report results here.
What i discovered is that the asoundrc implementation of the filter call is VERY sensitive to commas and spacing. If you tried using Charlie's filters with commas, no good; if you tried spaces, also no good. After an hour or two of head-scratching trial and error, I retyped the filter command string exactly as you see here. Don't copy and paste, because there may be unicode character weirdness!


It will be very interesting to see how much work you can extract from the RPi! If, in fact, the ACDf filters are now completely functional on the BBB, then there will be lots of interesting cross comparisons. So keeping up the dialogue will probably be worthwhile. I think Charlie will be glad to hear that the ACDf filters are working in ALSA plugins. Since you are the one to have cracked that, at some point why not post a "success" notice (plus a link to this discussion) on Charlie's filter thread?


I also noticed a link to this Alsa implementation thread in a comment on Richard Taylor's blog. He expressed skepticism regarding the focus on 'bit-perfect' signals. As a buzzword 'bit-perfect' has a checkered past with many interpretations. Now with linux renderers like the BBB, RPi, etc., - very simple processors with customizable clocks - the jury can become more definitive on the role of clocking/resampling. What do I hear when PCM is synthesized under control of a 'native sampling frequency' clock? Exclusive of the filtering in ALSA, bad recordings sound even worse, good recordings clearly sound even better. My immediate objective here is to make the crossovers sound as transparent as the unfiltered DAC output that I can enjoy via headphones. But I'm not a bit-perfect evangelist. At some time in the future I would like to try resampling in HQPlayer. For now, ONWARD! 😀

Well, I don't so much care about "bit perfect audio" but if it's there, use it, right? The main reason not to resample to a single rate is to lower the overhead on the pi, which (you may notice from "top") is struggling with the web server - node.js is using 120% of a CPU core. So, I want to keep everything as performant as possible.

In case anyone cares, here's a pic of my system. The Pi is the glowing red light behind the Alon Model 1's; the AVR is a Harman/Kardon AVR254 with a dead channel; the baffles are two mis-matched pieces of shelving and table (they aren't even the same material!); the drivers are close-to-20-year-old aura 8000 rpm car subs, the tweeters are NHT (model unknown), and the mids are unknown parts express 5.25 -- the tweeters and mids won at the Burning amp raffle. How does this unholy amalgamation sound, you ask? In a word, pretty damn good! There's not much bass to speak of, but the mids and highs are open and the presence is sublime.

https://www.instagram.com/p/BCa4wsPl_yZ/
BTW, I have to shout out to my wife, because even *I* think this is a hideous mess 😀
 
Trouble. Crossover experimentation time about to become (more) scarce. FedEx just delivered a pair of these, and new Mundorf AMT tweeters are OTW...
 

Attachments

  • Lowther.jpg
    Lowther.jpg
    620.6 KB · Views: 230
Lucky you!
Crossovers may not be so necessary, but I forsee some notch filtering in your future 😀

An unholy alliance of digital and SET tube amps perhaps?

Nope, I'm done rolling tubes. I had a triode preamp that sounded SO sweet running NOS government radar surplus 6SN7s. After they were no longer available, nothing else measured up. I 'graduated' to an all balanced signal chain and have never looked back. I'm replacing some vintage JBL LE8T-H drivers, one of which is getting 'raspy'. The nice thing about a full range driver as midrange is that vocals can stay completely within the mid band. Cheating, perhaps, but it has been very effective in the past.
 
Just an update, I was able to add a second string of ACDf filters last night.
My next step is to try to replicate the install on a different distro, Volumio, because that seems to be quite popular amongst the audio crowd. Unfortunately, Volumio runs a different kernel version, so I can't just copy over the module I made for Jessie. C'est la vie. More hacking for me!
 
But for the heck of it, without upgrading Wheezy, I just copied and pasted the text for your left woofer lowpass filter into my asound.conf file. And??? ...segmentation faults again???

The little sucker ran!

Correction - after cold re-boot, the little sucker choked and killed the crossover. Could you do me a favor JR? Execute 'analyseplugin ACDf.so'. When I do so, I get:
Code:
root@botic:/data# analyseplugin ACDf.so

Plugin Name: "Active Crossover Designer LADSPA filters version 1.02"
Plugin Label: "ACDf"
Plugin Unique ID: 5221
Maker: "Charlie Laub, 2015"
Copyright: "GPLv3"
Must Run Real-Time: No
Has activate() Function: Yes
Has deactivate() Function: No
Has run_adding() Function: No
ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT NOT RUN_ADDING.
Environment: Normal or Hard Real-Time
Ports:	"ACD Filter Type" input, control, 0 to 29
	"Filter polarity; 1=normal, -1=reverse" input, control, -1 to 1
	"Filter Gain in dB" input, control
	"Filter Pole Frequency in Hertz" input, control
	"Filter Pole Q" input, control
	"Filter Zero Frequency in Hertz" input, control
	"Filter Zero Q" input, control
	"Input" input, audio, -1 to 1
	"Output" output, audio, -1 to 1

Note that the version is labeled 1.02 even though I re-installed a freshly downloaded .tar of version 1.03. But the 'run_adding' notification is ominous...

I converted the RT filters to ACDf filters. When I tried something simple like 'speaker-test -c2' I got 'bus error'. So I removed the overlapping filters 4 and 5 from the 'filter1' plug (renumbered 6&7 to 4&5), completely removed the inactive 'delay' plug, and ran speaker-test again. NOW we see the same segmentation fault error message that I got before. Serious issues...

TIA for posting analyseplugin result,

Frank
 
Correction - after cold re-boot, the little sucker choked and killed the crossover. Could you do me a favor JR? Execute 'analyseplugin ACDf.so'. When I do so, I get:
Code:
root@botic:/data# analyseplugin ACDf.so

Plugin Name: "Active Crossover Designer LADSPA filters version 1.02"
Plugin Label: "ACDf"
Plugin Unique ID: 5221
Maker: "Charlie Laub, 2015"
Copyright: "GPLv3"
Must Run Real-Time: No
Has activate() Function: Yes
Has deactivate() Function: No
Has run_adding() Function: No
ERROR: PLUGIN HAS SET_RUN_ADDING_GAIN FUNCTION BUT NOT RUN_ADDING.
Environment: Normal or Hard Real-Time
Ports:	"ACD Filter Type" input, control, 0 to 29
	"Filter polarity; 1=normal, -1=reverse" input, control, -1 to 1
	"Filter Gain in dB" input, control
	"Filter Pole Frequency in Hertz" input, control
	"Filter Pole Q" input, control
	"Filter Zero Frequency in Hertz" input, control
	"Filter Zero Q" input, control
	"Input" input, audio, -1 to 1
	"Output" output, audio, -1 to 1

Note that the version is labeled 1.02 even though I re-installed a freshly downloaded .tar of version 1.03. But the 'run_adding' notification is ominous...

I converted the RT filters to ACDf filters. When I tried something simple like 'speaker-test -c2' I got 'bus error'. So I removed the overlapping filters 4 and 5 from the 'filter1' plug (renumbered 6&7 to 4&5), completely removed the inactive 'delay' plug, and ran speaker-test again. NOW we see the same segmentation fault error message that I got before. Serious issues...

TIA for posting analyseplugin result,

Frank

If you find some odd behavior or are having problems you could always ask try the ACDf designer about it...

It looks like I forgot to change the version identifier when I released 1.03. I will make a note of it. You can change it yourself by editing the code. Go to line 452 of ACDf.cpp:
Code:
text = "Active Crossover Designer LADSPA filters version 1.02";
Change the 1.02 at the end of the line to 1.03 and save the file. Then at the command prompt in that directory, type:
Code:
make clean
make
sudo make install


You can ignore the "ominous" run_adding gain error. Run adding is disabled, so this really doesn't mean anything. I vaguely recall seeing this when I was debugging the code but encountered some issue when trying to fix it (e.g. it caused some other error). Again, since run_adding mode can't be used the error can be safely ignored. I will see if I can get this cleared up in the next release.

SPEEDING UP YOUR ACDf PLUGINS
I've been wondering if anyone has been bothering to edit the compiler directives (in the Makefile) for their machines? These are specified after the CFLAGS variable on that line (line 6) of the Makefile. Better performance (e.g. speed) can be obtained by directing the compiler to optimize the code for the CPU architecture of the machine on which the plugins are running. I touch on this in the README file under the section "Optimizing the code for faster execution on your hardware". I had to leave out any optimization directives because this can vary from machine to machine and what works for (e.g) the Pi would not work on another hardware platform (e.g. BBB, etc.). As new hardware becomes available (Pi 3, Next Thing Co. "CHIP") the compiler directives used must be adapted to the new hardware (CPU).
 
Charlie, Thanks for monitoring and for the above information! I'm very excited by JR's results, and really hope to crack the problem on my rig. ...in due time.

Right now I'm finishing up tweaks on a few new electronics pieces, and am deep into cabinetmaker-mode. Two all new speaker cabinet designs plus a coordinating equipment cabinet - trying to max the WAF. When all that is done, then it will be time to really refine things with the ACDf filters. So my angst level remains manageable. 😉

I (will) have the same question re: Makefile edits. Perhaps one of these optimizations would work for JR?
http://www.diyaudio.com/forums/pc-b...ng-linux-audio-crossovers-14.html#post4394186

And, we are not done learning the best ways to structure multiple filter chains in ALSA. I'll contribute where I can, but my platform remains 'mute' for now.

All the best!

Frank
 
Correction - after cold re-boot, the little sucker choked and killed the crossover. Could you do me a favor JR? Execute 'analyseplugin ACDf.so'.

I converted the RT filters to ACDf filters. When I tried something simple like 'speaker-test -c2' I got 'bus error'. So I removed the overlapping filters 4 and 5 from the 'filter1' plug (renumbered 6&7 to 4&5), completely removed the inactive 'delay' plug, and ran speaker-test again. NOW we see the same segmentation fault error message that I got before. Serious issues...

TIA for posting analyseplugin result,

Frank

Hey Frank, I can't right now because I'm kernel hacking on Volumio (because I'm a glutton for punishment). But it is probably a simple issue. Care to post your asoundrc file? Also, post your error message when you run speaker-test. Those can be quite helpful. Next, if you are feeling brave, you can run sudo speaker-test ... that will *make* speaker test run. That can be helpful if you hear the setup fail. I was running sudo speaker-test and could hear that woofer 1 was going to the left woofer, but woofer2 was going to my right tweeter!
Also, try doing the export ladspa plugin location thing. That may die when you reboot if you don't have it in your environment variables somewhere.

That's all I got for ideas of why it may not be working.

@Charlie, thanks for jumping on the thread.

The hacking continues...
 
Status
Not open for further replies.