hifiscan


Namehifiscan JSON
Version 1.4.3 PyPI version JSON
download
home_pagehttps://github.com/erdewit/hifiscan
SummaryOptimize the audio quality of loudspeakers
upload_time2023-03-11 17:12:00
maintainer
docs_urlNone
authorEwald R. de Wit
requires_python>=3.8
licenseBSD
keywords frequency impulse response audio spectrum equalizer
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            |PyVersion| |Status| |PyPiVersion| |License|

Introduction
============

The goal of HiFiScan is to help equalize an audio system to get
the best possible audio quality from it.
There are two ways to do this:

1. Manual: The realtime frequency response is displayed and
the peaks and troughs can be interactively equalized away.

2. Automatic: The frequency response is measured and a correction
is calculated. This correction is by default a phase-neutral finite impulse
response (FIR) that can be imported into most equalizer programs.

The measuring is done by playing a "chirp" sound that sweeps
across all frequencies and recording how loud each frequency comes out
of the speakers. A good microphone is needed, with a wide frequency range
and preferably with a flat frequency response.

The equalization itself is not provided; It can be performed by an
equalizer of your choice, such as
`EasyEffects <https://github.com/wwmm/easyeffects/>`_
for Linux,
`Equalizer APO <https://sourceforge.net/projects/equalizerapo/>`_
and
`Peace <https://sourceforge.net/projects/peace-equalizer-apo-extension/>`_
for Windows, or
`eqMac <https://eqmac.app/>`_ for macOS.

Installation
============

::

    pip install -U hifiscan

The program is started from a console by typing::

    hifiscan

All functionality is also available for interactive use in
`this Jupyter notebook <chirp.ipynb>`_.

Examples
========

Laptop
------

Lets first optimize the speakers of a laptop.
The laptop has tiny down-firing speakers and a massive
case resonance that makes it sound about as bad as it gets.

The sound is recorded with a USB studio microphone; The built-in
microphone of the laptop is not suitable for this.

.. image:: images/laptop_setup.jpg

Letting the measurements run it becomes clear just how bad
the spectrum is, with a peak at 1 kHz about 20 dB above average.
Every 10 dB is a factor 10 in power, so 20 dB is a factor 100.

The low frequency is set to 200 Hz since the laptop can't possibly
output anything below this.

.. image:: images/laptop-spectrum.png

To get an automatic correction, we go to the "Impulse Response" section
(selectable in the lower left corner). From here it's possible to use
all-default values and click straight on "Export as WAV" to get a
perfectly adequate result.

But lets optimize a bit further for this laptop. There are various
tradeoffs that can be made, one of which involves the **Duration**
of the impulse. A longer duration gives better bass control,
but also adds more latency.
The latency added by the equalizer is halve the duration of the impulse.
Since the laptop has no bass anyway, we choose a 22 ms duration for a
super-low 11 ms latency. This is less time than it takes sound to travel
four meters and is good enough even for gaming or video-calls.

We also increase the **Range** to 27 dB to get just a little bit of
extra equalization.

The lower graph (in brown) shows how the equalized spectrum is expected
to be, and it looks nicely flattened.

.. image:: images/laptop-IR.png

So lets export the impulse response and import
it into EasyEffects (In Convolver effect: "Impulses -> Import Impulse"
and then "Load"):

.. image:: images/Convolver.png

We go back to the spectrum measurement and store the uncorrected
spectrum with the **Store** button (to compare with later measurements).
More measurements can be stored as well, for example where the microphone
is placed in different locatations, The total average of the stored
measurements is shown in orange

Measuring the equalized system gives this:

.. image:: images/laptop-flattened-spectrum.png

It is seen that the equalization works by attenuation only:
Everything gets chopped to some level under the top (27 dB here)
and this flattens the whole landscape.

All this attenuation does decrease the total loudness, so the
volume has to be turned up to get the same loudness. This also
brings up the flanks of the spectrum and increases the effective
frequency range. There's a very welcome 40 Hz of extra bass and
a whole lot of treble:

.. image:: images/laptop-spectrum-equivolume.png

This is the point to leave the graphs and start to listen to
some music. Is there an improvement? There are of course lots
of different tastes in what sounds good, but for those who like
a neutrally balanced sound there is a huge improvement. Voices
are also much easier to understand.

The lack of bass is somewhat offset by the
`missing fundamental <https://en.wikipedia.org/wiki/Missing_fundamental>`_
phenomenon, were the brain "adds" a missing low frequency based on
its higher frequency harmonics. It seems that by equalizing the
harmonics the phantom bass gets equalized as well.

HiFi Stereo
-----------

The HiFi installation has four JBL surround loudspeakers wired
in series as a 2x2 stereo setup, plus a subwoofer. The sound
can only be described as very dull, as if the tweeters are
not working.

To calibrate we use the same microphone as for the laptop,
which is a Superlux E205UMKII.
Lets this time correct for any non-flatness of the microphone.
According to the documentation
it has this frequency response:

.. image:: images/mic_response.png

We create a text file that describes the microphone's frequency response::

  20 -1.5
  150 0
  4500 0
  10000 4
  17000 0
  20000 -2

The file is imported with "Corrections... -> Mic Calibration -> Load".
Manifucturer-supplied calibration files can be imported here as well.

Measuring the spectrum bears out the concerning lack
of treble:

.. image:: images/stereo-spectrum.png

So lets go to the Impulse Response section to fix this.

The **Range** is set to 33 dB - this is an extreme value but what the heck.

The **Tapering** is left at 5. It pulls the flanks of the Impulse
Response closer to zero (visible in the green curve), which also has
a smoothing effect on the spectrum. A value less than 5 might leave
the flanks of the green curve too high and this can cause nasty
`pre-echos <https://en.wikipedia.org/wiki/Pre-echo>`_.
A value higher than 5 might cause too much smoothing of the bass
region.

The **Smoothing** will also smooth the spectrum, but the smoothing is
done proportional to the frequency. It will smooth the bass region
less, allowing for better precision there. A good smoothing value
can be judged from the Correction Factor graph (in red): It should
be smooth with nicely rounded corners, yet with enough detail.

The **Duration** is fiddled with until an acceptable bass response is
reached (visible in lowest graph in brown).

.. image:: images/stereo-ir.png

After exporting the Impulse Response and importing it into
EasyEffects the result looks promising.

.. image:: images/stereo-spectrum-corrected.png

We turn up the volume to get the same loudness as before and
apply some visual smoothing to the spectrum for clarity.
It turns out that the tweeters can
do their job if only the amplifier drives them 100 times as hard.

.. image:: images/stereo-final.png

The difference in sound quality is night and day. Music is really
really good now. For movies it brings very immersive
action and excellent clarity of dialogue.

As mentioned in the introduction, the equalization is phase-
neutral. This means that despite the heavy and steep equalization
there are no relative phase shifts added. The details in a
lossless source of music (such as the bounces of a cymbal)
remain as crisp as can be.

As an aside, the amplifier used is a $18 circuit board based on the
`TPA3116D2 digital amplifier chip <https://www.ti.com/product/TPA3116D2>`_.
It draws 1.1 Watt while playing which only increases if the subwoofer
is really busy.

Bluetooth headphones
--------------------

HiFiScan is not intended for use with headphones. There is
the
`AutoEq project <https://github.com/jaakkopasanen/AutoEq>`_
with ready-made corrections for most headphones, Even so,
it can be used for experiments. For example, I have very
nice Dali IO-4 headphones that can be used with Bluetooth
or passively with an analog audio cable. It sounds better with
Bluetooth, which suggests that some equalization
is taking place. Lets measure this!

.. image:: images/dali.jpg

It is seen that there is a indeed a bit of active tuning
going on, although most of the tuning is done acoustically.
In orange is bluetooth and in cyan is the analog cable.
There's a wide -10dB attenuation at 1.8 kHz and a narrow -4dB one at 5.5 kHz.
This tuning can be applied to the analog signal to get the same sound as
with Bluetooth.

.. image:: images/dali-spectrum.png

Using a target curve
--------------------

Instead of aiming for a flat spectrum, it's also possible to target
a specific curve. This is done by creating a text file with the target
curve and importing it with "Corrections... -> Target Curve -> Load".
Lets use this zig-zagging target curve::

  300 -10
  500 10
  1000 5
  2000 10
  4000 10
  6000 0
  20000 -10

In the Impulse Response section we see in the lower graph that
a fit is made to the red line, which is the target curve.

.. image:: images/target_IR.png

The impulse with the baked-in target spectrum is exported and imported
into EasyEffects. In orange is the original spectrum, in red is the target
and in cyan the reshaped spectrum that tries to follow the target curve:

.. image:: images/target_spectrum.png


.. |PyPiVersion| image:: https://img.shields.io/pypi/v/hifiscan.svg
   :alt: PyPi
   :target: https://pypi.python.org/pypi/hifiscan

.. |PyVersion| image:: https://img.shields.io/badge/python-3.8+-blue.svg
   :alt:

.. |Status| image:: https://img.shields.io/badge/status-stable-green.svg
   :alt:

.. |License| image:: https://img.shields.io/badge/license-BSD-blue.svg
   :alt:

Causality
---------

The default is to create a phase-neutral (aka linear-phase)
impulse response. It's also possible to create a minimum-phase response.
Even everything in between is possible. This is done with the **Causality**
parameter, where 0% is phase-neutral and 100% is minimum-phase.
By varying the causality a smooth transition between the extremes is made:

.. image:: images/causality-waveform.png

The latency decreases proportional to the causality.
At 100% the response becomes zero-latency and purely causal, where only the current
and past sound samples are used. The pre-echo is eliminated at the price of
twice the post-echo.
Note that despite the name of "minimum-phase"
this setting actually incurs the most phase distortion, which can get severe with
a steep equalization.

A good compromise may be a causality of 40%, which reduces the pre-echo
by about 6 dB while not phase-smearing too much.
Let your ears be the judge of what sounds best.

A tool for changing the causality of existing impulse responses (as WAV file)
is found in "Tools... -> Change IR causality".

Disclaimer
==========

The software is provided on the conditions of the simplified BSD license.
Any blown speakers or shattered glasses are on you.

Enjoy,

:author: Ewald de Wit <ewald.de.wit@gmail.com>

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/erdewit/hifiscan",
    "name": "hifiscan",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "frequency impulse response audio spectrum equalizer",
    "author": "Ewald R. de Wit",
    "author_email": "ewald.de.wit@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/1a/77/1e464a455f45ac0de4b2f79cbcb4c184e5cfcb551cfbf9d32c47095bd6e1/hifiscan-1.4.3.tar.gz",
    "platform": null,
    "description": "|PyVersion| |Status| |PyPiVersion| |License|\n\nIntroduction\n============\n\nThe goal of HiFiScan is to help equalize an audio system to get\nthe best possible audio quality from it.\nThere are two ways to do this:\n\n1. Manual: The realtime frequency response is displayed and\nthe peaks and troughs can be interactively equalized away.\n\n2. Automatic: The frequency response is measured and a correction\nis calculated. This correction is by default a phase-neutral finite impulse\nresponse (FIR) that can be imported into most equalizer programs.\n\nThe measuring is done by playing a \"chirp\" sound that sweeps\nacross all frequencies and recording how loud each frequency comes out\nof the speakers. A good microphone is needed, with a wide frequency range\nand preferably with a flat frequency response.\n\nThe equalization itself is not provided; It can be performed by an\nequalizer of your choice, such as\n`EasyEffects <https://github.com/wwmm/easyeffects/>`_\nfor Linux,\n`Equalizer APO <https://sourceforge.net/projects/equalizerapo/>`_\nand\n`Peace <https://sourceforge.net/projects/peace-equalizer-apo-extension/>`_\nfor Windows, or\n`eqMac <https://eqmac.app/>`_ for macOS.\n\nInstallation\n============\n\n::\n\n    pip install -U hifiscan\n\nThe program is started from a console by typing::\n\n    hifiscan\n\nAll functionality is also available for interactive use in\n`this Jupyter notebook <chirp.ipynb>`_.\n\nExamples\n========\n\nLaptop\n------\n\nLets first optimize the speakers of a laptop.\nThe laptop has tiny down-firing speakers and a massive\ncase resonance that makes it sound about as bad as it gets.\n\nThe sound is recorded with a USB studio microphone; The built-in\nmicrophone of the laptop is not suitable for this.\n\n.. image:: images/laptop_setup.jpg\n\nLetting the measurements run it becomes clear just how bad\nthe spectrum is, with a peak at 1 kHz about 20 dB above average.\nEvery 10 dB is a factor 10 in power, so 20 dB is a factor 100.\n\nThe low frequency is set to 200 Hz since the laptop can't possibly\noutput anything below this.\n\n.. image:: images/laptop-spectrum.png\n\nTo get an automatic correction, we go to the \"Impulse Response\" section\n(selectable in the lower left corner). From here it's possible to use\nall-default values and click straight on \"Export as WAV\" to get a\nperfectly adequate result.\n\nBut lets optimize a bit further for this laptop. There are various\ntradeoffs that can be made, one of which involves the **Duration**\nof the impulse. A longer duration gives better bass control,\nbut also adds more latency.\nThe latency added by the equalizer is halve the duration of the impulse.\nSince the laptop has no bass anyway, we choose a 22 ms duration for a\nsuper-low 11 ms latency. This is less time than it takes sound to travel\nfour meters and is good enough even for gaming or video-calls.\n\nWe also increase the **Range** to 27 dB to get just a little bit of\nextra equalization.\n\nThe lower graph (in brown) shows how the equalized spectrum is expected\nto be, and it looks nicely flattened.\n\n.. image:: images/laptop-IR.png\n\nSo lets export the impulse response and import\nit into EasyEffects (In Convolver effect: \"Impulses -> Import Impulse\"\nand then \"Load\"):\n\n.. image:: images/Convolver.png\n\nWe go back to the spectrum measurement and store the uncorrected\nspectrum with the **Store** button (to compare with later measurements).\nMore measurements can be stored as well, for example where the microphone\nis placed in different locatations, The total average of the stored\nmeasurements is shown in orange\n\nMeasuring the equalized system gives this:\n\n.. image:: images/laptop-flattened-spectrum.png\n\nIt is seen that the equalization works by attenuation only:\nEverything gets chopped to some level under the top (27 dB here)\nand this flattens the whole landscape.\n\nAll this attenuation does decrease the total loudness, so the\nvolume has to be turned up to get the same loudness. This also\nbrings up the flanks of the spectrum and increases the effective\nfrequency range. There's a very welcome 40 Hz of extra bass and\na whole lot of treble:\n\n.. image:: images/laptop-spectrum-equivolume.png\n\nThis is the point to leave the graphs and start to listen to\nsome music. Is there an improvement? There are of course lots\nof different tastes in what sounds good, but for those who like\na neutrally balanced sound there is a huge improvement. Voices\nare also much easier to understand.\n\nThe lack of bass is somewhat offset by the\n`missing fundamental <https://en.wikipedia.org/wiki/Missing_fundamental>`_\nphenomenon, were the brain \"adds\" a missing low frequency based on\nits higher frequency harmonics. It seems that by equalizing the\nharmonics the phantom bass gets equalized as well.\n\nHiFi Stereo\n-----------\n\nThe HiFi installation has four JBL surround loudspeakers wired\nin series as a 2x2 stereo setup, plus a subwoofer. The sound\ncan only be described as very dull, as if the tweeters are\nnot working.\n\nTo calibrate we use the same microphone as for the laptop,\nwhich is a Superlux E205UMKII.\nLets this time correct for any non-flatness of the microphone.\nAccording to the documentation\nit has this frequency response:\n\n.. image:: images/mic_response.png\n\nWe create a text file that describes the microphone's frequency response::\n\n  20 -1.5\n  150 0\n  4500 0\n  10000 4\n  17000 0\n  20000 -2\n\nThe file is imported with \"Corrections... -> Mic Calibration -> Load\".\nManifucturer-supplied calibration files can be imported here as well.\n\nMeasuring the spectrum bears out the concerning lack\nof treble:\n\n.. image:: images/stereo-spectrum.png\n\nSo lets go to the Impulse Response section to fix this.\n\nThe **Range** is set to 33 dB - this is an extreme value but what the heck.\n\nThe **Tapering** is left at 5. It pulls the flanks of the Impulse\nResponse closer to zero (visible in the green curve), which also has\na smoothing effect on the spectrum. A value less than 5 might leave\nthe flanks of the green curve too high and this can cause nasty\n`pre-echos <https://en.wikipedia.org/wiki/Pre-echo>`_.\nA value higher than 5 might cause too much smoothing of the bass\nregion.\n\nThe **Smoothing** will also smooth the spectrum, but the smoothing is\ndone proportional to the frequency. It will smooth the bass region\nless, allowing for better precision there. A good smoothing value\ncan be judged from the Correction Factor graph (in red): It should\nbe smooth with nicely rounded corners, yet with enough detail.\n\nThe **Duration** is fiddled with until an acceptable bass response is\nreached (visible in lowest graph in brown).\n\n.. image:: images/stereo-ir.png\n\nAfter exporting the Impulse Response and importing it into\nEasyEffects the result looks promising.\n\n.. image:: images/stereo-spectrum-corrected.png\n\nWe turn up the volume to get the same loudness as before and\napply some visual smoothing to the spectrum for clarity.\nIt turns out that the tweeters can\ndo their job if only the amplifier drives them 100 times as hard.\n\n.. image:: images/stereo-final.png\n\nThe difference in sound quality is night and day. Music is really\nreally good now. For movies it brings very immersive\naction and excellent clarity of dialogue.\n\nAs mentioned in the introduction, the equalization is phase-\nneutral. This means that despite the heavy and steep equalization\nthere are no relative phase shifts added. The details in a\nlossless source of music (such as the bounces of a cymbal)\nremain as crisp as can be.\n\nAs an aside, the amplifier used is a $18 circuit board based on the\n`TPA3116D2 digital amplifier chip <https://www.ti.com/product/TPA3116D2>`_.\nIt draws 1.1 Watt while playing which only increases if the subwoofer\nis really busy.\n\nBluetooth headphones\n--------------------\n\nHiFiScan is not intended for use with headphones. There is\nthe\n`AutoEq project <https://github.com/jaakkopasanen/AutoEq>`_\nwith ready-made corrections for most headphones, Even so,\nit can be used for experiments. For example, I have very\nnice Dali IO-4 headphones that can be used with Bluetooth\nor passively with an analog audio cable. It sounds better with\nBluetooth, which suggests that some equalization\nis taking place. Lets measure this!\n\n.. image:: images/dali.jpg\n\nIt is seen that there is a indeed a bit of active tuning\ngoing on, although most of the tuning is done acoustically.\nIn orange is bluetooth and in cyan is the analog cable.\nThere's a wide -10dB attenuation at 1.8 kHz and a narrow -4dB one at 5.5 kHz.\nThis tuning can be applied to the analog signal to get the same sound as\nwith Bluetooth.\n\n.. image:: images/dali-spectrum.png\n\nUsing a target curve\n--------------------\n\nInstead of aiming for a flat spectrum, it's also possible to target\na specific curve. This is done by creating a text file with the target\ncurve and importing it with \"Corrections... -> Target Curve -> Load\".\nLets use this zig-zagging target curve::\n\n  300 -10\n  500 10\n  1000 5\n  2000 10\n  4000 10\n  6000 0\n  20000 -10\n\nIn the Impulse Response section we see in the lower graph that\na fit is made to the red line, which is the target curve.\n\n.. image:: images/target_IR.png\n\nThe impulse with the baked-in target spectrum is exported and imported\ninto EasyEffects. In orange is the original spectrum, in red is the target\nand in cyan the reshaped spectrum that tries to follow the target curve:\n\n.. image:: images/target_spectrum.png\n\n\n.. |PyPiVersion| image:: https://img.shields.io/pypi/v/hifiscan.svg\n   :alt: PyPi\n   :target: https://pypi.python.org/pypi/hifiscan\n\n.. |PyVersion| image:: https://img.shields.io/badge/python-3.8+-blue.svg\n   :alt:\n\n.. |Status| image:: https://img.shields.io/badge/status-stable-green.svg\n   :alt:\n\n.. |License| image:: https://img.shields.io/badge/license-BSD-blue.svg\n   :alt:\n\nCausality\n---------\n\nThe default is to create a phase-neutral (aka linear-phase)\nimpulse response. It's also possible to create a minimum-phase response.\nEven everything in between is possible. This is done with the **Causality**\nparameter, where 0% is phase-neutral and 100% is minimum-phase.\nBy varying the causality a smooth transition between the extremes is made:\n\n.. image:: images/causality-waveform.png\n\nThe latency decreases proportional to the causality.\nAt 100% the response becomes zero-latency and purely causal, where only the current\nand past sound samples are used. The pre-echo is eliminated at the price of\ntwice the post-echo.\nNote that despite the name of \"minimum-phase\"\nthis setting actually incurs the most phase distortion, which can get severe with\na steep equalization.\n\nA good compromise may be a causality of 40%, which reduces the pre-echo\nby about 6 dB while not phase-smearing too much.\nLet your ears be the judge of what sounds best.\n\nA tool for changing the causality of existing impulse responses (as WAV file)\nis found in \"Tools... -> Change IR causality\".\n\nDisclaimer\n==========\n\nThe software is provided on the conditions of the simplified BSD license.\nAny blown speakers or shattered glasses are on you.\n\nEnjoy,\n\n:author: Ewald de Wit <ewald.de.wit@gmail.com>\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "Optimize the audio quality of loudspeakers",
    "version": "1.4.3",
    "split_keywords": [
        "frequency",
        "impulse",
        "response",
        "audio",
        "spectrum",
        "equalizer"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "64e483aa35a74dafa9c2b23b9de222797002df4afe4656f34d404bb8013d07f7",
                "md5": "8195fe47037d11b575d96446ef0bc00c",
                "sha256": "adcb4b35cf7cbac02d83406a587f1354ef187b8bd8ac47d42e46263bafe5b551"
            },
            "downloads": -1,
            "filename": "hifiscan-1.4.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8195fe47037d11b575d96446ef0bc00c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 20025,
            "upload_time": "2023-03-11T17:11:58",
            "upload_time_iso_8601": "2023-03-11T17:11:58.901959Z",
            "url": "https://files.pythonhosted.org/packages/64/e4/83aa35a74dafa9c2b23b9de222797002df4afe4656f34d404bb8013d07f7/hifiscan-1.4.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1a771e464a455f45ac0de4b2f79cbcb4c184e5cfcb551cfbf9d32c47095bd6e1",
                "md5": "e6b2b134c9e4f998dd8d53036a8f61b6",
                "sha256": "1e883fbe3b203d5e5ffe3b2563dbc258e81dc7f6751b8b31d22a92a28ee2ee5f"
            },
            "downloads": -1,
            "filename": "hifiscan-1.4.3.tar.gz",
            "has_sig": false,
            "md5_digest": "e6b2b134c9e4f998dd8d53036a8f61b6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 23708,
            "upload_time": "2023-03-11T17:12:00",
            "upload_time_iso_8601": "2023-03-11T17:12:00.251458Z",
            "url": "https://files.pythonhosted.org/packages/1a/77/1e464a455f45ac0de4b2f79cbcb4c184e5cfcb551cfbf9d32c47095bd6e1/hifiscan-1.4.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-03-11 17:12:00",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": "erdewit",
    "github_project": "hifiscan",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "hifiscan"
}
        
Elapsed time: 0.19106s