• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

DIY Active Cardioid Implementation Using Global Optimization Algorithm

P.L.

Member
Joined
Jan 22, 2025
Messages
11
Likes
104
Location
S.Korea
I am a speaker enthusiast in South Korea who enjoys DIY speaker projects and am primarily active on the DCInside speaker gallery (a Korean website) under the same username. I have been engaged in this topic for more than a year as a post-work hobby. Through this post, I would like to share some of the results of my work, and hope to offer ideas to others who would like to do DIY cardioid projects.


Terminology:
In this article, the terms “active” and “passive” do not refer to amplification or crossover network types but rather to two methods of achieving cardioid directivity in speakers. In active cardioid systems, two or more independently operating drivers are used to achieve cardioid directivity (as in the Kii Three). In contrast, passive cardioid systems recycle the rear wave of a driver by using resistive materials inside the enclosure and emitting it through precisely engineered slits (for example, in the D&D 8c). There also exists a method employing multiple drivers dependent on passive crossover networks (although I have not encountered any commercial examples), which I also classify as passive implementation.


1. Introduction
Due to physical constraints, speakers tend to be omnidirectional at low frequencies—and this effect can extend to higher frequencies as the speaker size decreases. Such behavior may lead to unwanted early reflections, which can degrade the listening experience, especially in smaller rooms.
One solution to overcome these physical limitations is the cardioid system. By reproducing a time-delayed, phase-inverted sound wave at a specific point behind the speaker driver, rearward sound waves can be effectively canceled. This creates a heart-shaped directivity pattern, known as a cardioid.

theory.jpg


These days, this cardioid technology is widely adopted in the high-end speaker industry. However, while the theory is well-known, practical implementation methodologies remain scarce.
Furthermore, most DIY discussions around cardioid systems focus on passive implementations. Companies like Geithain, Dutch & Dutch, and Sigberg use this technology by making slits in the speaker enclosure, filling the interior with acoustically absorptive materials, and leveraging the rear wave of the driver escaping through the slits to achieve cardioid directivity. However, this method is highly dependent on factors such as driver size, enclosure design, slit dimensions and shape, and the uniformity and density of the absorptive materials, therefore requiring iterative testing with multiple enclosures. While simulators like AKABAK can help in this process, accurately simulating internal absorptive materials remains a challenge.
Active implementation, while less efficient and requiring multiple DSP channels and amplifiers, allows for greater flexibility in modifying driver frequency responses via DSP and reduces dependency on enclosure design, making it more suitable for DIY applications.
Among active cardioid speakers, one of the most popular models is the Kii Three. The Kii Three employs a 3-way (excluding the tweeter) cardioid technology with a midrange driver, two side woofers, and two rear woofers to achieve full-range cardioid directivity. The following is a video in which Bruto Putzey, the developer of the Kii Three, explains its operating principles.


Other active cardioid models, such as the Kii Seven, Mesanovic CDM65, and GGNTKT M1, typically employ only side or rear woofers (thereby 2-way) to achieve cardioid directivity. Since optimizing a 3-way cardioid inherently includes the optimization process for 2-way systems, this post focuses solely on implementing 3-way cardioid systems like the Kii Three. In my experience, optimizing a 2-way cardioid system is much simpler compared to a 3-way system and can easily be done manually.
Optimization of a 3-way cardioid system is quite challenging to approach initially. This post aims to demonstrate that the desired polar pattern can be achieved by adopting a simple optimization algorithm and using modern computational power.


2. Preliminaries
2.1 Speaker Build

I designed an enclosure by referencing the structure of the Kii Three. The crucial point here is that the acoustic center distance between the midrange driver and the side woofers has to be kept as short as possible. In active cardioid systems, the distance between these acoustic centers is one of the most critical factors.

modeling.png


The enclosure was divided into three chambers: one each for the tweeter and midrange, and one for the side and rear woofers. For simplicity, the system was constructed without internal amplifiers, using only a single 4-pin SpeakON connector. DAC, DSP, and amplifiers are located externally. Specifically, I used the following equipment, all of which can be replaced with alternatives:
  • Motu Ultralite mk5 audio interface with DAW
  • 3e Audio 260-2-29A * 4
  • SEAS H1499-06 27TBCD/GB-DXT * 1
  • SB Acoustics SB15NBAC * 1
  • Dayton DCS165-4 * 4


2.2 Measurement
Accurate measurement is very crucial to minimize discrepancies between simulated and actual results. A good guide for quasi-anechoic measurements is available here:
https://www.audiosciencereview.com/...ents-spinoramas-with-rew-and-vituixcad.21860/

Ground plane measurements can also be used if sufficient accuracy is ensured. I was fortunate enough to use a full-anechoic chamber with a cutoff frequency of approximately 100 Hz. Measurements were conducted using an Earthworks M30 microphone and a custom motorized turntable controlled by Arduino. The image below is my first setup, when I didn't build the motorized turntable yet.

first_setup.png


In the measurement, maintaining consistent time references across all drivers during measurements is critical, as active cardioid systems are highly sensitive to relative time delays. In my setup, REW’s loopback reference feature was used to ensure timing consistency. I obtained four measurements by individually measuring the tweeter, midrange, side woofers, and rear woofers. However, measuring the tweeter and midrange as a single driver by crossing them over is perfectly acceptable, and actually more efficient in terms of VRAM usage.
While Spinorama requires 10° measurement intervals, I advocate for 5° or even 3° intervals to enable more precise adjustments to the desired directivity pattern. For 3° interval measurements, a total of 960 measurements are required for 4 drivers, so it is highly recommended to build a motorized turntable and automate the measurement process.


2.3 Tweeter Crossover
Crossover the tweeter and midrange drivers. This process is explained in detail by purifi-audio on their blog, so refer to the following link:
https://purifi-audio.com/blog/tech-notes-1/time-phase-alignment-acoustic-center-lobing-etc-14


3. Optimization
3.1 Theoretical Background

Ideally, a perfect cardioid pattern can be achieved by placing two perfectly omnidirectional drivers at an appropriate distance, inverting the phase of the rear driver, and applying a delay corresponding to that distance.

ideal_cardioid.png


In practical implementation, it is advisable for a specific bass driver to be low-passed. This can be easily implemented using a simple second-order crossover filter (alternatively, a more complex FIR filter could be employed).

practical_iir_cardioid.png


In reality, the two drivers mounted in the enclosure exhibit directional mismatches. Since modifying a driver’s response in specific directions is impossible, the primary objective is to ensure the combined response achieves the desired directivity pattern, while the secondary objective is to maximize rear cancellation.
The primary objective can be easily achieved using simple IIR filters if the speaker is properly designed for active cardioid. However, the secondary objective is considerably more complex. Instead of mathematically deriving the ideal filters, I opted for a simpler approach: leveraging modern computing power. While VituixCAD offers a similar optimization feature called “Optimizer”, it has limitations in setting desired targets and, due to its reliance on CPU processing, exhibits significant constraints when exploring high-dimensional variables.
To find the desired solution, I applied Particle Swarm Optimization (PSO), a straightforward optimization algorithm based on swarm intelligence. In PSO, individual particles work together to explore the solution space efficiently. This approach allows each particle to be easily parallelized on GPUs using PyTorch. For a detailed description, refer to:
https://en.wikipedia.org/wiki/Particle_swarm_optimization


3.2 Parameter Setup
The optimization parameters were:
  • Midrange: 1 HPF (LR12), 2 allpass filters
  • Side woofer: 1 LPF (LR12), 10 PEQs, 1 delay, 2 allpass filters
  • Rear woofer: 1 LPF (LR12), 10 PEQs, 1 delay, 2 allpass filters

The PEQs spanned frequencies from 100 Hz to 1000 Hz on a logarithmic scale, with gains ranging from –6 to 6 dB and Q factors from 1 to 5. The optimization cost was defined as the normalized SPL average between 100 Hz–1000 Hz and 90°–180°. To prevent excessive convergence at specific positions, SPL values below –30 dB were clamped to –30 dB in simulation. A constraint was added to ensure that the –3 dB point between 200 Hz–1000 Hz fell within 57°–63°. I used the Nvidia A100 for the experiment, and to verify whether effective exploration is possible with common GPUs, RTX 3070 and Google Colab were also utilized.

For faster convergence, it is advisable to appropriately define the range of each parameter and select suitable initial values. It doesn't need extreme precision and can be easily be achieved using VituixCAD. Here is an example image showing my initial values.

initial.png


3.3 Algorithm
  • Input:
    • X ∈ ℝ^(D×A×F×3)            (each element = (f, SPL, φ))
    • B ∈ ℝ^(n×2)               (parameter bounds: [min, max] for each of n parameters)
    • N ∈ ℕ                (number of particles)
    • T ∈ ℕ                (maximum iterations)
    • w ∈ ℝ, c₁ ∈ ℝ, c₂ ∈ ℝ    (inertia weight and acceleration coefficients)
    • (Optional) θ₍init₎ ∈ ℝⁿ      (custom initial parameter vector)
    • Objective function f(θ, X) defined via a signal processing pipeline
  • Output:
    • θ_best ∈ ℝⁿ minimizing f(θ, X)
  • Step 1: Initialization
    For i = 1, 2, …, N:
      • θᵢ ← random value ∈ B           (or set θᵢ = θ₍init₎ if provided)
      • vᵢ ← random velocity
      • pᵢ ← θᵢ                    (personal best)
      • Compute cost cᵢ = f(θᵢ, X)
    End for
    Set global best:
      θ_best ← argmin₍ᵢ₌₁…N₎ f(θᵢ, X)
  • Step 2: Define the Processing Pipeline (Objective Function f)
    f(θ, X) is computed by:
      a. Applying parametric peak filters using filter parameters extracted from θ.
      b. Applying crossover filtering (e.g., HPF/LPF via Linkwitz-Riley)
      c. Applying delays according to delay parameters.
      d. Applying allpass filtering according to allpass parameters
      e. Combining driver outputs (via complex summation) and normalizing the result.
      f. Evaluating cost based on averaged SPL and penalty conditions (if thresholds on frequency/angle are exceeded).
  • Step 3: Phase 1 – Exploration
    For t = 1 to T:
      For each particle i:
        Compute cᵢ = f(θᵢ, X)
        If cᵢ < f(pᵢ, X), then set pᵢ ← θᵢ
      End for
      Update global best:
        θ_best ← θⱼ, where f(θⱼ, X) = min { f(θ₁, X), f(θ₂, X), …, f(θ_N, X) }
      For each particle i, update:
        vᵢ ← w·vᵢ + c₁·r₁·(pᵢ – θᵢ) + c₂·r₂·(θ_best – θᵢ)
        θᵢ ← clamp(θᵢ + vᵢ, B)       (ensure θᵢ ∈ B)
    End for
  • Step 4: Phase 2 – Exploitation
    Repeat the update loop until the improvement Δ in f(θ_best, X) over a fixed checkpoint interval is less than a predefined threshold:
      • Recompute cᵢ = f(θᵢ, X) for all i
      • Update personal bests pᵢ and global best θ_best as in Step 3
      • Update velocities vᵢ and positions θᵢ as in Step 3
      • Terminate when Δ < ε (a small threshold)
  • Step 5: Return
    Output θ_best and its associated cost f(θ_best, X).


4. Results
Since this is not an academic paper, detailed data on the convergence process is omitted. Only the directivity plot of the final result data is shared here.
The simulated result:

simulation.png


The measurement result:

measurement.png


Despite my efforts to reduce measurement errors, a noticeable degree of error still remained. This underscores the importance of precise measurement.


5. Observations
The following observations were made in this experiment:
  1. When the same target is set, although the individual parameters may differ significantly, they ultimately converge in a similar shape.
  2. Even if a specific parameter is fixed, the desired directivity can still be achieved provided that sufficient degrees of freedom are available for the other parameters to compensate.
  3. While utilizing a good GPU facilitates more parallel computations at once, it was not a strict requirement for this method. When initial values are appropriately provided, even the free GPU allocation on Google Colab was sufficient to achieve a satisfactory level of convergence.
  4. Selecting appropriate hyperparameters (w, c₁, c₂) and adjusting them during the search process contributes to faster convergence.


6. Conclusion
I explored the process of optimizing a 3-way active cardioid system using a global optimization algorithm. These results demonstrate the following:
  1. Directivity comparable to that of premium commercial cardioid speakers can be achieved.
  2. It demonstrated the potential to automate the traditional manual and iterative simulation process.
  3. Although this algorithm inherently suffers from multiple local minima, with sufficient iterations, the overall response eventually converges with a consistent solution, rendering this drawback inconsequential.

The optimization program was developed entirely from scratch using Python. Since it was developed specifically for this project and, as it is tailored to my experimental setup, it cannot be generalized for public release. Therefore, it is not shared here, but I have provided a detailed description of the algorithm used.

Working on several cardioid projects, I noticed that information on this topic is surprisingly scarce. I hope this article offers some inspiration to DIY enthusiasts.
 
Wow this is really amazing! Thank you for sharing this! Awesome to see how you applied algorithms to optomize for such a complicated puzzle.

Might it be possible to adapt your algorithm to a more general one, where one could change it to one's variables and inputs?

PS. could you show your filters in the end result? I'm curious what you ended up with!
 
Might it be possible to adapt your algorithm to a more general one, where one could change it to one's variables and inputs?
PS. could you show your filters in the end result? I'm curious what you ended up with!
The algorithm I provided is a generalized algorithm.
Since filters are highly dependent on the enclosure design and the speaker drivers, my final results are meaningless. If I could have provided generalized filters, I would have shared the particular filters instead of the method for finding them.
 
Thank you for your generous contribution in willingly sharing this excellent process.
 
This is one of the most information-rich DIY posts I've ever seen, and the techniques seem pretty advanced for DIY. I would actually bet good money that some, maybe most speaker brands aren't using such sophisticated optimization tools. I personally wouldn't know how to start implementing this, but it's very interesting despite being a little over my head.

Not that you should have shared focus with this in your main post, but I am curious as to your impressions listening to this speaker with the optimized filters in place.

Thanks for sharing all this!
 
Not that you should have shared focus with this in your main post, but I am curious as to your impressions listening to this speaker with the optimized filters in place.
Since I am not a trained listener, I try to avoid making subjective evaluations.
Actually, my motivation for building speakers is primarily driven by engineering curiosity rather than a quest for superior sound.
 
Actually, my motivation for building speakers is primarily driven by engineering curiosity rather than a quest for superior sound.
That's pretty remarkable! Usually people are motivated at least somewhat by a desire for better speakers for their own use.

Well, what you posted looks like a really good result. Very controlled directivity down to 100hz and even a bit below is not something you find on budget mid-fi speakers, to put it mildly.

Maybe your interest in superior sound will grow if you spend some time listening to them. :) Although now it occurs to me, maybe you only built one? :oops:
 
That's pretty remarkable! Usually people are motivated at least somewhat by a desire for better speakers for their own use.

Well, what you posted looks like a really good result. Very controlled directivity down to 100hz and even a bit below is not something you find on budget mid-fi speakers, to put it mildly.

Maybe your interest in superior sound will grow if you spend some time listening to them. :) Although now it occurs to me, maybe you only built one? :oops:
This might not only be by scientific interest ... Ascilab is from the same origin :cool:
 
This might not only be by scientific interest ... Ascilab is from the same origin :cool:
Yes, clearly there is something good happening in the DIY / audio startup scene in South Korea. It makes me wonder if Samsung is taking notes for their subsidiary Harman...
 
Maybe your interest in superior sound will grow if you spend some time listening to them.
The fact that my primary motivation for building this speaker was engineering curiosity does not imply that I lack appreciation or interest in the sound quality of a good speaker. I have previously owned a pair of Genelec 8361, and I believe that if one's sole aim were to obtain excellent sound, there would be little need for a DIY approach.

Although now it occurs to me, maybe you only built one?
This speaker represents my 4th cardioid project. To date, I have built three active cardioids and one passive cardioid, and I have plans for a 5th project later this year. Should the opportunity arise, I will also introduce them as well.
 
I am a speaker enthusiast in South Korea who enjoys DIY speaker projects and am primarily active on the DCInside speaker gallery (a Korean website) under the same username. I have been engaged in this topic for more than a year as a post-work hobby. Through this post, I would like to share some of the results of my work, and hope to offer ideas to others who would like to do DIY cardioid projects.


Terminology:
In this article, the terms “active” and “passive” do not refer to amplification or crossover network types but rather to two methods of achieving cardioid directivity in speakers. In active cardioid systems, two or more independently operating drivers are used to achieve cardioid directivity (as in the Kii Three). In contrast, passive cardioid systems recycle the rear wave of a driver by using resistive materials inside the enclosure and emitting it through precisely engineered slits (for example, in the D&D 8c). There also exists a method employing multiple drivers dependent on passive crossover networks (although I have not encountered any commercial examples), which I also classify as passive implementation.


1. Introduction
Due to physical constraints, speakers tend to be omnidirectional at low frequencies—and this effect can extend to higher frequencies as the speaker size decreases. Such behavior may lead to unwanted early reflections, which can degrade the listening experience, especially in smaller rooms.
One solution to overcome these physical limitations is the cardioid system. By reproducing a time-delayed, phase-inverted sound wave at a specific point behind the speaker driver, rearward sound waves can be effectively canceled. This creates a heart-shaped directivity pattern, known as a cardioid.

View attachment 432892

These days, this cardioid technology is widely adopted in the high-end speaker industry. However, while the theory is well-known, practical implementation methodologies remain scarce.
Furthermore, most DIY discussions around cardioid systems focus on passive implementations. Companies like Geithain, Dutch & Dutch, and Sigberg use this technology by making slits in the speaker enclosure, filling the interior with acoustically absorptive materials, and leveraging the rear wave of the driver escaping through the slits to achieve cardioid directivity. However, this method is highly dependent on factors such as driver size, enclosure design, slit dimensions and shape, and the uniformity and density of the absorptive materials, therefore requiring iterative testing with multiple enclosures. While simulators like AKABAK can help in this process, accurately simulating internal absorptive materials remains a challenge.
Active implementation, while less efficient and requiring multiple DSP channels and amplifiers, allows for greater flexibility in modifying driver frequency responses via DSP and reduces dependency on enclosure design, making it more suitable for DIY applications.
Among active cardioid speakers, one of the most popular models is the Kii Three. The Kii Three employs a 3-way (excluding the tweeter) cardioid technology with a midrange driver, two side woofers, and two rear woofers to achieve full-range cardioid directivity. The following is a video in which Bruto Putzey, the developer of the Kii Three, explains its operating principles.


Other active cardioid models, such as the Kii Seven, Mesanovic CDM65, and GGNTKT M1, typically employ only side or rear woofers (thereby 2-way) to achieve cardioid directivity. Since optimizing a 3-way cardioid inherently includes the optimization process for 2-way systems, this post focuses solely on implementing 3-way cardioid systems like the Kii Three. In my experience, optimizing a 2-way cardioid system is much simpler compared to a 3-way system and can easily be done manually.
Optimization of a 3-way cardioid system is quite challenging to approach initially. This post aims to demonstrate that the desired polar pattern can be achieved by adopting a simple optimization algorithm and using modern computational power.


2. Preliminaries
2.1 Speaker Build

I designed an enclosure by referencing the structure of the Kii Three. The crucial point here is that the acoustic center distance between the midrange driver and the side woofers has to be kept as short as possible. In active cardioid systems, the distance between these acoustic centers is one of the most critical factors.

View attachment 432901

The enclosure was divided into three chambers: one each for the tweeter and midrange, and one for the side and rear woofers. For simplicity, the system was constructed without internal amplifiers, using only a single 4-pin SpeakON connector. DAC, DSP, and amplifiers are located externally. Specifically, I used the following equipment, all of which can be replaced with alternatives:
  • Motu Ultralite mk5 audio interface with DAW
  • 3e Audio 260-2-29A * 4
  • SEAS H1499-06 27TBCD/GB-DXT * 1
  • SB Acoustics SB15NBAC * 1
  • Dayton DCS165-4 * 4


2.2 Measurement
Accurate measurement is very crucial to minimize discrepancies between simulated and actual results. A good guide for quasi-anechoic measurements is available here:
https://www.audiosciencereview.com/...ents-spinoramas-with-rew-and-vituixcad.21860/

Ground plane measurements can also be used if sufficient accuracy is ensured. I was fortunate enough to use a full-anechoic chamber with a cutoff frequency of approximately 100 Hz. Measurements were conducted using an Earthworks M30 microphone and a custom motorized turntable controlled by Arduino. The image below is my first setup, when I didn't build the motorized turntable yet.

View attachment 432895

In the measurement, maintaining consistent time references across all drivers during measurements is critical, as active cardioid systems are highly sensitive to relative time delays. In my setup, REW’s loopback reference feature was used to ensure timing consistency. I obtained four measurements by individually measuring the tweeter, midrange, side woofers, and rear woofers. However, measuring the tweeter and midrange as a single driver by crossing them over is perfectly acceptable, and actually more efficient in terms of VRAM usage.
While Spinorama requires 10° measurement intervals, I advocate for 5° or even 3° intervals to enable more precise adjustments to the desired directivity pattern. For 3° interval measurements, a total of 960 measurements are required for 4 drivers, so it is highly recommended to build a motorized turntable and automate the measurement process.


2.3 Tweeter Crossover
Crossover the tweeter and midrange drivers. This process is explained in detail by purifi-audio on their blog, so refer to the following link:
https://purifi-audio.com/blog/tech-notes-1/time-phase-alignment-acoustic-center-lobing-etc-14


3. Optimization
3.1 Theoretical Background

Ideally, a perfect cardioid pattern can be achieved by placing two perfectly omnidirectional drivers at an appropriate distance, inverting the phase of the rear driver, and applying a delay corresponding to that distance.

View attachment 432896

In practical implementation, it is advisable for a specific bass driver to be low-passed. This can be easily implemented using a simple second-order crossover filter (alternatively, a more complex FIR filter could be employed).

View attachment 432897

In reality, the two drivers mounted in the enclosure exhibit directional mismatches. Since modifying a driver’s response in specific directions is impossible, the primary objective is to ensure the combined response achieves the desired directivity pattern, while the secondary objective is to maximize rear cancellation.
The primary objective can be easily achieved using simple IIR filters if the speaker is properly designed for active cardioid. However, the secondary objective is considerably more complex. Instead of mathematically deriving the ideal filters, I opted for a simpler approach: leveraging modern computing power. While VituixCAD offers a similar optimization feature called “Optimizer”, it has limitations in setting desired targets and, due to its reliance on CPU processing, exhibits significant constraints when exploring high-dimensional variables.
To find the desired solution, I applied Particle Swarm Optimization (PSO), a straightforward optimization algorithm based on swarm intelligence. In PSO, individual particles work together to explore the solution space efficiently. This approach allows each particle to be easily parallelized on GPUs using PyTorch. For a detailed description, refer to:
https://en.wikipedia.org/wiki/Particle_swarm_optimization


3.2 Parameter Setup
The optimization parameters were:
  • Midrange: 1 HPF (LR12), 2 allpass filters
  • Side woofer: 1 LPF (LR12), 10 PEQs, 1 delay, 2 allpass filters
  • Rear woofer: 1 LPF (LR12), 10 PEQs, 1 delay, 2 allpass filters

The PEQs spanned frequencies from 100 Hz to 1000 Hz on a logarithmic scale, with gains ranging from –6 to 6 dB and Q factors from 1 to 5. The optimization cost was defined as the normalized SPL average between 100 Hz–1000 Hz and 90°–180°. To prevent excessive convergence at specific positions, SPL values below –30 dB were clamped to –30 dB in simulation. A constraint was added to ensure that the –3 dB point between 200 Hz–1000 Hz fell within 57°–63°. I used the Nvidia A100 for the experiment, and to verify whether effective exploration is possible with common GPUs, RTX 3070 and Google Colab were also utilized.

For faster convergence, it is advisable to appropriately define the range of each parameter and select suitable initial values. It doesn't need extreme precision and can be easily be achieved using VituixCAD. Here is an example image showing my initial values.

View attachment 432898

3.3 Algorithm
  • Input:
    • X ∈ ℝ^(D×A×F×3)            (each element = (f, SPL, φ))
    • B ∈ ℝ^(n×2)               (parameter bounds: [min, max] for each of n parameters)
    • N ∈ ℕ                (number of particles)
    • T ∈ ℕ                (maximum iterations)
    • w ∈ ℝ, c₁ ∈ ℝ, c₂ ∈ ℝ    (inertia weight and acceleration coefficients)
    • (Optional) θ₍init₎ ∈ ℝⁿ      (custom initial parameter vector)
    • Objective function f(θ, X) defined via a signal processing pipeline
  • Output:
    • θ_best ∈ ℝⁿ minimizing f(θ, X)
  • Step 1: Initialization
    For i = 1, 2, …, N:
      • θᵢ ← random value ∈ B           (or set θᵢ = θ₍init₎ if provided)
      • vᵢ ← random velocity
      • pᵢ ← θᵢ                    (personal best)
      • Compute cost cᵢ = f(θᵢ, X)
    End for
    Set global best:
      θ_best ← argmin₍ᵢ₌₁…N₎ f(θᵢ, X)
  • Step 2: Define the Processing Pipeline (Objective Function f)
    f(θ, X) is computed by:
      a. Applying parametric peak filters using filter parameters extracted from θ.
      b. Applying crossover filtering (e.g., HPF/LPF via Linkwitz-Riley)
      c. Applying delays according to delay parameters.
      d. Applying allpass filtering according to allpass parameters
      e. Combining driver outputs (via complex summation) and normalizing the result.
      f. Evaluating cost based on averaged SPL and penalty conditions (if thresholds on frequency/angle are exceeded).
  • Step 3: Phase 1 – Exploration
    For t = 1 to T:
      For each particle i:
        Compute cᵢ = f(θᵢ, X)
        If cᵢ < f(pᵢ, X), then set pᵢ ← θᵢ
      End for
      Update global best:
        θ_best ← θⱼ, where f(θⱼ, X) = min { f(θ₁, X), f(θ₂, X), …, f(θ_N, X) }
      For each particle i, update:
        vᵢ ← w·vᵢ + c₁·r₁·(pᵢ – θᵢ) + c₂·r₂·(θ_best – θᵢ)
        θᵢ ← clamp(θᵢ + vᵢ, B)       (ensure θᵢ ∈ B)
    End for
  • Step 4: Phase 2 – Exploitation
    Repeat the update loop until the improvement Δ in f(θ_best, X) over a fixed checkpoint interval is less than a predefined threshold:
      • Recompute cᵢ = f(θᵢ, X) for all i
      • Update personal bests pᵢ and global best θ_best as in Step 3
      • Update velocities vᵢ and positions θᵢ as in Step 3
      • Terminate when Δ < ε (a small threshold)
  • Step 5: Return
    Output θ_best and its associated cost f(θ_best, X).


4. Results
Since this is not an academic paper, detailed data on the convergence process is omitted. Only the directivity plot of the final result data is shared here.
The simulated result:

View attachment 432899

The measurement result:

View attachment 432900

Despite my efforts to reduce measurement errors, a noticeable degree of error still remained. This underscores the importance of precise measurement.


5. Observations
The following observations were made in this experiment:
  1. When the same target is set, although the individual parameters may differ significantly, they ultimately converge in a similar shape.
  2. Even if a specific parameter is fixed, the desired directivity can still be achieved provided that sufficient degrees of freedom are available for the other parameters to compensate.
  3. While utilizing a good GPU facilitates more parallel computations at once, it was not a strict requirement for this method. When initial values are appropriately provided, even the free GPU allocation on Google Colab was sufficient to achieve a satisfactory level of convergence.
  4. Selecting appropriate hyperparameters (w, c₁, c₂) and adjusting them during the search process contributes to faster convergence.


6. Conclusion
I explored the process of optimizing a 3-way active cardioid system using a global optimization algorithm. These results demonstrate the following:
  1. Directivity comparable to that of premium commercial cardioid speakers can be achieved.
  2. It demonstrated the potential to automate the traditional manual and iterative simulation process.
  3. Although this algorithm inherently suffers from multiple local minima, with sufficient iterations, the overall response eventually converges with a consistent solution, rendering this drawback inconsequential.

The optimization program was developed entirely from scratch using Python. Since it was developed specifically for this project and, as it is tailored to my experimental setup, it cannot be generalized for public release. Therefore, it is not shared here, but I have provided a detailed description of the algorithm used.

Working on several cardioid projects, I noticed that information on this topic is surprisingly scarce. I hope this article offers some inspiration to DIY enthusiasts.

Huge thanks for sharing this! This is some seriously impressive work, and I really appreciate the level of detail!
Are you planning to publish a paper on this? It would be super interesting to see this in a more formal write-up!

Also, I'd love to try replicating your optimization approach - would you be open to sharing the 960 measurements? And if it's not too much to ask, could you also share the enclosure and turntable project details? (Not really my area of expertise, but I'd love to learn more.)

But unfortunately, I think it would be very difficult to replicate your results without proper measurement equipment, but I still find this incredibly inspiring.

Again, thanks a ton for this post! Really amazing work.
 
Huge thanks for sharing this! This is some seriously impressive work, and I really appreciate the level of detail!
Are you planning to publish a paper on this? It would be super interesting to see this in a more formal write-up!

Also, I'd love to try replicating your optimization approach - would you be open to sharing the 960 measurements? And if it's not too much to ask, could you also share the enclosure and turntable project details? (Not really my area of expertise, but I'd love to learn more.)

But unfortunately, I think it would be very difficult to replicate your results without proper measurement equipment, but I still find this incredibly inspiring.

Again, thanks a ton for this post! Really amazing work.

1. I don't plan on making any formal publications. It's 100% pure hobby.

2. This thread is intended for intermediate-level DIY enthusiasts who know how to perform quasi-anechoic measurements. It's quick to learn. I can't provide my measurement data, but if you invest a little time (a whole Sunday will do) to follow the link I've mentioned step by step, you can easily obtain your own measurement data.

3. My enclosure is difficult to replicate since it involves CNC and router machining. Since active cardioids don't heavily depend on the enclosure shape, try designing one yourself to suit the drivers you'll use.
Also, my turntable is relatively crude, so it's better to reach out to the person who made that impressive piece.
 
Thanks for sharing. Very impressive work and results - except for your midband sidelobes - if I can say so without causing offense. I'll bet your cost/optimization algorithm doesn't care much about them. It would be interesting to see if you can enhance your algorithm to minimize them.

If you were doing this manually you likely could have reduced them by carefully tailoring the phase and amplitude responses of your side drivers in those regions, although you would need FIR for best results. With FIR you can precisely control the phase; with IIR you adjust relative amplitudes of front and side drivers at problem points.

I've been working on a cardioid coax for some time and favor passive cardioid coax midwoofer crossing to active cardioid bass subsystem at 200 Hz. In doing the active cardioid, I found that the Vituix FIR "phase eq" PEQ was my best friend for minimizing sidelobes. When I switched to IIR only, I was surprised how well I could do just with DSP delay and using shelf filters instead of high pass and low pass filters, as you have done. In my work so far, I have ABEC simulations instead of measurements and do the optimization manually in Vituix. That has not been so difficult as to move me to (try to)develop an optimization script. The key is to first define the IIR filter to shape the forward response, then look at its group delay, then adjust the delay on the amplifier block in the sim to compensate that group delay as best you can over the target cardioid response region. Then do the same for the cardioid drivers, continually increasing there DSP delay in perhaps 200 usec steps until you see the rejection to the rear as seen on a Horizontal line chart starts to grow.

Here is a horizontal line chart from one of my sims that uses only IIR filters for the cardioid. The red/orange hump centered on 340 Hz is a sidelobe but its well down the amplitude slope, so I don't care about it. I have sims of similar system using FIR all the way where that sidelobe is killed using phase EQ PEQs, as described earlier. These projects are so much more practical if the need for high precision FIR at low frequencies is eliminated. Seeing your results with IIR is one of the things that finally got me to try it!
Floorstand_QuadSides Directivity (hor).png
 
Very very impressive project, congrats!

Dayton DCS165-4 * 4

Was there a reason for this particular choice of woofers? From how I read their parameters, I thought they would be limited in excursion to perform any cancellation operation at higher SPL, and also require a fair amount of boost below 80Hz, so eating up your amp´s power pretty quickly.
 
Thanks for sharing. Very impressive work and results - except for your midband sidelobes - if I can say so without causing offense. I'll bet your cost/optimization algorithm doesn't care much about them. It would be interesting to see if you can enhance your algorithm to minimize them.

If you were doing this manually you likely could have reduced them by carefully tailoring the phase and amplitude responses of your side drivers in those regions, although you would need FIR for best results. With FIR you can precisely control the phase; with IIR you adjust relative amplitudes of front and side drivers at problem points.
Thank you for sharing your know-how. I also believe that a coaxial cardioid is an attractive DIY option. I found great motivation from the following thread when I started my projects (although I haven’t attempted myself yet, as I’m still waiting for a coaxial DIY driver that meets my criteria):
http://www.hifi-forum.de/viewthread-104-28780-5.html

As you mentioned, the final response can certainly be further optimized manually. But this post is about an experiment to demonstrate the feasibility of a certain idea. If the goal were to produce a commercial product, much finer tuning would likely be necessary.
(fyi the speaker used in this experiment—tentatively named RFC2—was discarded after this experiment to make room for my next project.)

Also, as I mentioned in the post, cardioid optimization between two drivers is much simpler than with three. Since this write-up deals with 3-way optimization, there was a need to automate the process.

Was there a reason for this particular choice of woofers? From how I read their parameters, I thought they would be limited in excursion to perform any cancellation operation at higher SPL, and also require a fair amount of boost below 80Hz, so eating up your amp´s power pretty quickly.
Mainly because it was cheap :) and has been used in a commercial application — Mesanovic CDM65.
I agree it was not an ideal choice for higher standards.
 
Thank you for your contribution to DIY and DCgallery communities! First time seeing your generalized algorithm. Simply mind boggling.
 
Mainly because it was cheap :) and has been used in a commercial application — Mesanovic CDM65.

Ah, that is an interesting one. Looks like a DYI clone of Kii Seven utilizing some standard amp module. I thought all Dayton Audio drivers are cheap ;-)

Looking at the THD measurements, it seems the main shortcoming of the bass driver is its behavior below 75Hz. Probably running into excursion limits, or insufficient power. Regarding cardioid, it seems to be much better than I initially thought, at least above 180Hz when the cardioid fully kicks in in this example.

Have quite some listening experience with cardioids, and my feelings are mixed. I subjectively feel that the transition between cardioid and non-cardioid is audible in many cases, and that many compact models easily leave the comfort zone of their bass drivers when driven with the wrong material. That said, I came to the conclusion that models with bigger bass drivers meet my expectations, like the 15" or 18" MEG (one 12" model was superb as well, though).
 
Last edited:
Back
Top Bottom