• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. 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!

Audyssey Manual Calibration “OCA’s REW + Audyssey Awesomeness”

a_L0neWolf

New Member
Joined
Feb 23, 2024
Messages
1
Likes
1
Location
CA
@OCA Thank you for the guidance; your videos are very helpful.

I managed to run down, and these are my results
2-22 ART.jpg
 
  • Like
Reactions: OCA

DeLub

Active Member
Joined
Jun 16, 2020
Messages
135
Likes
178
Location
The Netherlands
OCA created an even more automated approach explained in this video
.

@OCA, what I noticed is that you don't allow any boost anymore up to 200Hz. In a previous video you were using a max of 5dB if I remember correctly. Why is that?

While I do agree with your insight that the room should not be corrected above a certain frequency, I think the speaker response should be corrected. As my speakers are on spinorama.org, I entered the EQs found there in REW and multiplied them with the antiHF curve. E.g. for my bookshelf speaker I use as a surround the resulting curve is:
filters.png

I changed the generateFilters() function to wait to allow me to load the set of filters in REW, and after the steps that were already there, I did a merge from the spinorama filter to the one generated by the code. It sounds good to me, but what do you think of this idea?

JavaScript:
  async function generateFilters() {
    console.info(`Crafting custom room correction filters...`);
    delay *= 2;
    const measurements = await fetch_mREW();
    let indexTC = dChannels + 1;
    await postNext('Minimum phase version', indexTC, {
      "include cal": false,
      "append lf tail": false,
      "append hf tail": false,
      "frequency warping": false,
      "replicate data": false
    });
    await postDelete(indexTC);
    await fetch_mREW(indexTC,'PUT', {title: "Dr Toole target curve"});
    await new Promise(resolve => setTimeout(resolve, delay * 1.15));

    const result1 = await swal.fire({
      confirmButtonColor: "#6fa3e7",
      text: "Import the speaker targets",
      input: 'text',
      showCancelButton: true
    });

    for (let i = 1; i <= dChannels; i++)
    {
      await postNext('Minimum phase version', i, {
        "include cal": false,
        "append lf tail": false,
        "append hf tail": false,
        "frequency warping": false,
        "replicate data": false
      });
      ii = 2* dChannels + i * 2;
      
      await postNext('Arithmetic', [ii, indexTC], {
        function: "A / B",
        regularisation: "0",
        lowerLimit: "0",
        upperLimit: "0"});
      await postNext('Arithmetic', [ii + 1, ii + 1], {
        function: "1 / A",
        maxGain: "0",
        lowerLimit: "0",
        upperLimit: "200",
        autoTarget: "0",
        excludeNotches: false});
      await postNext('Arithmetic', [dChannels + 1 + i, ii + 2], {
        function: "Merge B to A",
        mergeFrequency: "300",
        mergeBlend: true});
      await postNext('Minimum phase version', ii + 3, {
        "include cal": false,
        "append lf tail": false,
        "append hf tail": false,
        "frequency warping": false,
        "replicate data": false
      });
      await postNext('Arithmetic', [i, ii + 4], {function: "A * B"});
      const finTitle = measurements[i].title.replace("o","final");
      await fetch_mREW(ii + 5, 'PUT', {title: finTitle});
      const filtTitle = measurements[i].title.replace("o","");
      await fetch_mREW(ii + 4, 'PUT', {title: filtTitle});
      console.log(`Optimal filter generation for speaker ${filtTitle} is completed.`);


      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));


    }

    for (let xxx = 0; xxx < dChannels; xxx++) {
      await postDelete(dChannels + 2);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
    }

    console.log(`Done!`);
    console.info(`************************************************************************************************************************`);
  }
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
OCA created an even more automated approach explained in this video
.

@OCA, what I noticed is that you don't allow any boost anymore up to 200Hz. In a previous video you were using a max of 5dB if I remember correctly. Why is that?

While I do agree with your insight that the room should not be corrected above a certain frequency, I think the speaker response should be corrected. As my speakers are on spinorama.org, I entered the EQs found there in REW and multiplied them with the antiHF curve. E.g. for my bookshelf speaker I use as a surround the resulting curve is:
View attachment 358949
I changed the generateFilters() function to wait to allow me to load the set of filters in REW, and after the steps that were already there, I did a merge from the spinorama filter to the one generated by the code. It sounds good to me, but what do you think of this idea?

JavaScript:
  async function generateFilters() {
    console.info(`Crafting custom room correction filters...`);
    delay *= 2;
    const measurements = await fetch_mREW();
    let indexTC = dChannels + 1;
    await postNext('Minimum phase version', indexTC, {
      "include cal": false,
      "append lf tail": false,
      "append hf tail": false,
      "frequency warping": false,
      "replicate data": false
    });
    await postDelete(indexTC);
    await fetch_mREW(indexTC,'PUT', {title: "Dr Toole target curve"});
    await new Promise(resolve => setTimeout(resolve, delay * 1.15));

    const result1 = await swal.fire({
      confirmButtonColor: "#6fa3e7",
      text: "Import the speaker targets",
      input: 'text',
      showCancelButton: true
    });

    for (let i = 1; i <= dChannels; i++)
    {
      await postNext('Minimum phase version', i, {
        "include cal": false,
        "append lf tail": false,
        "append hf tail": false,
        "frequency warping": false,
        "replicate data": false
      });
      ii = 2* dChannels + i * 2;
     
      await postNext('Arithmetic', [ii, indexTC], {
        function: "A / B",
        regularisation: "0",
        lowerLimit: "0",
        upperLimit: "0"});
      await postNext('Arithmetic', [ii + 1, ii + 1], {
        function: "1 / A",
        maxGain: "0",
        lowerLimit: "0",
        upperLimit: "200",
        autoTarget: "0",
        excludeNotches: false});
      await postNext('Arithmetic', [dChannels + 1 + i, ii + 2], {
        function: "Merge B to A",
        mergeFrequency: "300",
        mergeBlend: true});
      await postNext('Minimum phase version', ii + 3, {
        "include cal": false,
        "append lf tail": false,
        "append hf tail": false,
        "frequency warping": false,
        "replicate data": false
      });
      await postNext('Arithmetic', [i, ii + 4], {function: "A * B"});
      const finTitle = measurements[i].title.replace("o","final");
      await fetch_mREW(ii + 5, 'PUT', {title: finTitle});
      const filtTitle = measurements[i].title.replace("o","");
      await fetch_mREW(ii + 4, 'PUT', {title: filtTitle});
      console.log(`Optimal filter generation for speaker ${filtTitle} is completed.`);


      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
      await postDelete(ii);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));


    }

    for (let xxx = 0; xxx < dChannels; xxx++) {
      await postDelete(dChannels + 2);
      await new Promise(resolve => setTimeout(resolve, delay * 1.15));
    }

    console.log(`Done!`);
    console.info(`************************************************************************************************************************`);
  }
Nicely coded but Merge A to B would shift phase and SPL of one or both of the responses to match them and can have major unforeseen effects. The right way is multiplying your additional filter with the final one.

That extra generated response would mess with the indices in the later parts of the code though. You are asking for more trouble and I bet you it's not going to sound better when you do ;)
 

DeLub

Active Member
Joined
Jun 16, 2020
Messages
135
Likes
178
Location
The Netherlands
That extra generated response would mess with the indices in the later parts of the code though.
I made sure to clean up after myself in order to not mess up the indices. I also removed the anti-HF stuff, as this is already compensated for in my filters.

Nicely coded but Merge A to B would shift phase and SPL of one or both of the responses to match them and can have major unforeseen effects. The right way is multiplying your additional filter with the final one.
Is it possible to only multiply from 300Hz and up?
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
I made sure to clean up after myself in order to not mess up the indices. I also removed the anti-HF stuff, as this is already compensated for in my filters.


Is it possible to only multiply from 300Hz and up?
You need a filter with 0dB freq magnitude and 0 degree phase response somewhere around 300Hz, merge it A B with a Dirac pulse (which you can create in EQ window with generate filters when there are no filters) at 300 Hz. Then you can multiply that merged response safely with the bass filter.
 

mosco

Member
Joined
Oct 19, 2020
Messages
18
Likes
15
Friend OCA's script has been asking for a cover for days, it's easy and fast.
As they say in my town
"Que bueno y que pronto le dijo la tonta al tonto"...
 

kifeep

Member
Joined
Dec 16, 2023
Messages
32
Likes
5
I did a merge from the spinorama filter to the one generated by the code.

The right way is multiplying your additional filter with the final one.

Is it possible to only multiply from 300Hz and up?


Curious if this alternative approach would work:
  1. Run A-1 without modification
  2. Create filter curves by only entering spinorama EQ data above 300 Hz
  3. Multiply the final filters generated by A-1 with these
  4. Export the multiplication results
  5. Use the older AudysseyX_OCA script to insert these into the ady file
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
Curious if this alternative approach would work:
  1. Run A-1 without modification
  2. Create filter curves by only entering spinorama EQ data above 300 Hz
  3. Multiply the final filters generated by A-1 with these
  4. Export the multiplication results
  5. Use the older AudysseyX_OCA script to insert these into the ady file
Yes, that would totally work but again, it wouldn't sound better ;) If you really have to, use the new automated shelving EQ filters of the REW beta for HF on gated frequency response.
 

kifeep

Member
Joined
Dec 16, 2023
Messages
32
Likes
5
Yes, that would totally work but again, it wouldn't sound better
Are you saying the general approach of correcting speaker (not room) FR above the transition frequency is inaudible or counterproductive? Or is there something about the method outlined that would fail to achieve the goal?
If you really have to, use the new automated shelving EQ filters of the REW beta for HF on gated frequency response.
So if one does try to correct speaker FR, why would filters based on a gated measurement be better than filters based on a NFS measurement? They are both meant to be quasi-anechoic, aren't they?

I'm really just trying to understand all this better. Thanks for your help.
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
Are you saying the general approach of correcting speaker (not room) FR above the transition frequency is inaudible or counterproductive?
The explanation is in the video (starts at the right time) above (#104).
They are both meant to be quasi-anechoic, aren't they?
Neither NF nor gated can measure the directions of the HF rays because you are using an "omnidirectional mic". There seems to be some confusion between headphone EQ and speaker EQ along the way. But between the two, I'd personally go for the old school gating method because I am not sure if these measurements or the algo used to EQ them is flawed but figures like below don't appear to me as anechoic response filter requirements of a speaker in this day and age:

index.php

There's also the "Gabor uncertainty" limit that deems windowing and filtering above a certain frequency not only meaningless but also harmful. Frequency dependent windowing starts violating the Gabor inequality at least in some small frequency range within which the room transfer function estimation becomes inaccurate and the room correction might be affected by appreciable errors in the evaluation of the room transfer function.

The gray line is the Gabor uncertainty limit which represents the fundamental limit of time and frequency resolution one can extract from a signal:



drc005.png

And if you can deviate a bit from the "everything you hear is only bias" idefix infecting this forum, remembering the hobby is ALL about "listening" and simply test by ear a -12dB peaking filter applied at 13,186Hz, you will never even question the idea again because you will instantly hear how throttled can your system suddenly sound.

Last but not least, here's Dr Floyd Toole's opinion on the matter:

 

kifeep

Member
Joined
Dec 16, 2023
Messages
32
Likes
5
Ok, thanks, this is really interesting.

The explanation is in the video (starts at the right time) above (#104).
I watched the video previously, but apparently misunderstood. It seemed, with the emphasis on reflections and directional cues, that it mostly applied to not filtering based on in-room measurements.

The argument for not filtering based on anechoic speaker response is much more subtle, and I suspect I'm not the only one who missed it. Is this a correct distillation of this second, finer point?:

1. Filtering based on quasi-anechoic (gated, NF, what-have-you) response seems like a good idea because it ignores reflected sound at the LP and purports to only affect the sound coming out of the speaker before any reflectivity in the room.

However,

2. Applying these filters will also affect off-access reproduction in unpredictable ways, which in turn affects reflected sound in-room and can reduce sound quality at the LP.

I'd personally go for the old school gating method because I am not sure if these measurements or the algo used to EQ them is flawed but figures like below don't appear to me as anechoic response filter requirements of a speaker in this day and age:
Those extreme spinorama filter examples are also fascinating. The generated EQ for my speakers doesn't have anything like that. I'm also mostly interested to see if there's room for improvement in the midrange. So I don't expect, in my case, that the difference would be instantly obvious or throttled. But if I find the time I might try it both ways just to see if I can tell the difference at all.

It might also be interesting to compare filters generated from a gated measurement with the ones on spinorama.org.
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
Ok, thanks, this is really interesting.


I watched the video previously, but apparently misunderstood. It seemed, with the emphasis on reflections and directional cues, that it mostly applied to not filtering based on in-room measurements.

The argument for not filtering based on anechoic speaker response is much more subtle, and I suspect I'm not the only one who missed it. Is this a correct distillation of this second, finer point?:

1. Filtering based on quasi-anechoic (gated, NF, what-have-you) response seems like a good idea because it ignores reflected sound at the LP and purports to only affect the sound coming out of the speaker before any reflectivity in the room.

However,

2. Applying these filters will also affect off-access reproduction in unpredictable ways, which in turn affects reflected sound in-room and can reduce sound quality at the LP.


Those extreme spinorama filter examples are also fascinating. The generated EQ for my speakers doesn't have anything like that. I'm also mostly interested to see if there's room for improvement in the midrange. So I don't expect, in my case, that the difference would be instantly obvious or throttled. But if I find the time I might try it both ways just to see if I can tell the difference at all.

It might also be interesting to compare filters generated from a gated measurement with the ones on spinorama.org.
There's recent work to properly measure directional sound vectors at the LP with spherical 64 mic arrays like this one:

 
Last edited:

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
if there's room for improvement in the midrange
Sort your bass and the rest will all come out beautifully. I don't think there're many speakers today with mids and highs that would audibly disturb listeners despite correct placement and toe-in.
 

DeLub

Active Member
Joined
Jun 16, 2020
Messages
135
Likes
178
Location
The Netherlands
I experimented with some of the options above, and also did not really like how the "spinorama version" turned out. I, of course, cannot draw any generic conclusions based on this, just my preference.

@OCA, instead of adding the anti-HF array to the result, why don't you limit equalization to 300Hz?
 

kifeep

Member
Joined
Dec 16, 2023
Messages
32
Likes
5
So just for fun, here are REW-generated filters from gated measurements vs filters generated by spinorama.org.

rew vs spin filters.png


In this particular case, it is evident that spinorama.org is less aggressive below 5k, but I'm sure that varies by speaker.

I don't know what to make of the large correction near 600 Hz, which is above the transition frequency, but sure seems room-related somehow. It's stuff like this that got me wondering what if any EQ would make sense in the midrange. Haven't had a chance yet to actually apply any of these and listen to the results.
 

kifeep

Member
Joined
Dec 16, 2023
Messages
32
Likes
5
Haven't had a chance yet to actually apply any of these and listen to the results.
Actually, that's not quite true. The EQ I'm listening to now is based on an earlier @OCA methodology and is very similar to the filters plotted above:

applied filters.png
 

OCA

Addicted to Fun and Learning
Forum Donor
Joined
Feb 2, 2020
Messages
679
Likes
499
Location
Germany
I experimented with some of the options above, and also did not really like how the "spinorama version" turned out. I, of course, cannot draw any generic conclusions based on this, just my preference.

@OCA, instead of adding the anti-HF array to the result, why don't you limit equalization to 300Hz?
Actually, I thought a lot about it and would normally not add filters that high but at the end I tried to make the exact reverse of what Audyssey does and avoid effecting the speaker's original output. However, I have been taking direct pre-amp out measurements in the last couple of days (and guess to add what to One) and I have reshaped that inverse filter. I'll upload that version very soon.
 

Hayabusa

Addicted to Fun and Learning
Joined
Oct 12, 2019
Messages
837
Likes
575
Location
Abu Dhabi
The new receivers have additional parameters in the JSON file that are not covered by the conversion program.
Things for multiple sub woofers and direction bass are not passed on.
 

PHD

Member
Joined
Mar 15, 2023
Messages
95
Likes
190
Hi

Can I use the Umik-1 to take measurements? Is it even possible to have REW send test tone to the elevation channels? Last time I checked it wasn't supported by any Windows audio driver such as ASIO.

Also, what about MINIDSP support for managing more than 2 subwoofers? My current calibration uses MINIDSP with 4 subwoofers and MSO calibration in which my Denon X6400H thinks I only have a single sub. Is this setup supported by the script?

Thanks
 
Top Bottom