Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: CI

on:
push:

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- run: docker compose run lab pnpm install

- run: docker compose run lab pnpm prettier --check .
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
data_mrs/*
.DS_Store
/.pnpm-store/
/data_mrs/
/devicePEQ/
/node_modules/
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/pnpm-lock.yaml
4 changes: 4 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"printWidth": 100,
"trailingComma": "all"
}
73 changes: 35 additions & 38 deletions Configuring.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Use Github or the email in my profile.
There are two other steps to show people FR graphs that I may not be
able to help with:

* Creating frequency response graphs in the first place. I have never
- Creating frequency response graphs in the first place. I have never
done this and don't know all the details. You might try reading
[this thread](https://www.head-fi.org/threads/general-iem-measurements-discussions.903455/)
for some information to get you started, and Crin is generally happy
to answer questions about measurement on [his Discord server](https://discord.gg/CtTqcCb).
* Hosting the pages. Believe it or not, I'm not a web developer and I
- Hosting the pages. Believe it or not, I'm not a web developer and I
don't know that much about setting up websites. One method that may
work for your purposes is to use Github Pages, which allows you to
serve the contents of any Github repository as a website. The main
Expand All @@ -30,20 +30,20 @@ able to help with:
These are the things you definitely need to change to make sure your
page works and isn't claiming it's crinacle.com.

* Set `DIR` in `config.js` and place your graphs and `phone_book.json`
- Set `DIR` in `config.js` and place your graphs and `phone_book.json`
there.
* Remove or change the watermark.
* Remove the `targets`, replace them with your own, or get permission
- Remove or change the watermark.
- Remove the `targets`, replace them with your own, or get permission
from Crinacle to use the ones in the CrinGraph repository.
* If you are using a free/premium model, change `premium_html` in
- If you are using a free/premium model, change `premium_html` in
`config_free.js` to point to your own site(s).

## Configuring CrinGraph

The main page used to display graphs is [graph.html](graph.html), which
defines the basic structure of a page and then includes a bunch of
Javascript files that do the real work (at the end of the file).
[graph_free.html](graph_free.html) is identical but uses a different
[graph_free.html](graph_free.html) is identical but uses a different
configuration file to remove some functionality. You will only need to
use it if you intend to have both a free and a paid graph tool.

Expand All @@ -54,29 +54,29 @@ can't!

Here are the current configuration parameters:

* `DIR` is the location of your FR graphs and the index for them
- `DIR` is the location of your FR graphs and the index for them
(see the next section). If you are displaying a cloned repository
using Github Pages, using a directory other than `data/` will make
merging changes from the main CrinGraph repository easier.
* `tsvParse` is a function which takes the text of an FR file and
- `tsvParse` is a function which takes the text of an FR file and
converts it to the format used internally by CrinGraph. See the next
section.
* `watermark` is a function that is applied once to the graph window on
- `watermark` is a function that is applied once to the graph window on
startup. The argument `svg` is a [d3](https://d3js.org/) selection
and you can use any d3 functionality to draw things in it. This part
must be changed, or you will end up impersonating crinacle.com! To
use no watermark, just delete the whole function body. You can also
delete, move, or change the image and text separately.
* `max_channel_imbalance` controls how sensitive the channel imbalance
- `max_channel_imbalance` controls how sensitive the channel imbalance
detector (that red exclamation mark that can show up in a headphone's
key) is. You probably don't need to change this.
* `targets` lists the available target frequency responses. If you don't
- `targets` lists the available target frequency responses. If you don't
want to display any targets set it to `false`. If you do use targets,
each one should be a file named `... Target.txt` in the `DIR`
directory you specified. The targets which are already there were
provided by Crinacle so make sure you have his permission before using
them.
* `scale_smoothing` (default 1) adjusts the level of smoothing applied
- `scale_smoothing` (default 1) adjusts the level of smoothing applied
at a given "Smooth:" setting. The setting will always start at 5, but
its value is multiplied by `scale_smoothing` to get the actual level
of smoothing.
Expand All @@ -86,12 +86,12 @@ of the graph tool. They are only present in
[config_free.js](config_free.js). If you don't set them the tool will
be unrestricted.

* `max_compare` is the maximum number of graphs allowed at a time.
* `disallow_target` prevents target FRs from ever being loaded.
* `allow_targets` is a list of target names, and overrides
- `max_compare` is the maximum number of graphs allowed at a time.
- `disallow_target` prevents target FRs from ever being loaded.
- `allow_targets` is a list of target names, and overrides
`disallow_target` for those targets, so they can be loaded. If
`disallow_target` isn't set, it has no effect.
* `premium_html` is the message shown when a user tries to do something
- `premium_html` is the message shown when a user tries to do something
which isn't allowed according to the previous two settings. Given that
it points to Crinacle's patreon and not yours, you probably want to
change it.
Expand All @@ -101,11 +101,11 @@ and different channel configurations than L/R. For example,
`config_hp.js` is intended for headphones and shows only the right
channel with five samples per channel.

* `default_channels` is a list of channels in each measurement: it
- `default_channels` is a list of channels in each measurement: it
defaults to `["L","R"]`. It's called "default" because I may add a
mechanism to change it for a single sample from `phone_book.json`,
but no such mechanism exists right now.
* `num_samples`, if set, is the number of samples in each channel.
- `num_samples`, if set, is the number of samples in each channel.
Samples are always numbered 1 to `num_samples`.

The following parameters are for setting the initial samples to display,
Expand All @@ -114,9 +114,9 @@ to reflect which samples are on the graph. Copying and opening that URL
will open the page with those samples shown. For these parameters a
headphone or target is identified by its filename.

* `init_phones` is a list of filenames to open by default.
* `share_url` enables URL sharing.
* `page_title` sets the page title display if URL sharing is enabled.
- `init_phones` is a list of filenames to open by default.
- `share_url` enables URL sharing.
- `page_title` sets the page title display if URL sharing is enabled.

## Storing your FR files

Expand All @@ -134,14 +134,11 @@ specify a different filepath. The file's contents are a list of brands,
where each brand is a list of models. A simple example of a brand:

```json
{
"name": "Elysian",
"suffix": "Acoustic Labs",
"phones": [ "Artemis"
, "Eros"
, "Minerva"
, "Terminator" ]
}
{
"name": "Elysian",
"suffix": "Acoustic Labs",
"phones": ["Artemis", "Eros", "Minerva", "Terminator"]
}
```

The only required attributes for a brand are its name ("name") and a
Expand All @@ -154,25 +151,25 @@ Each item in the "phones" array corresponds to a single headphone model.
While an item might just be the model name as shown above, there are
other possibilities as well. Two examples should cover most use cases:

* To use a different display name ("name") and filename ("file"): `{"name":"Carbo Tenore ZH-DX200-CT","file":"Tenore"}`
* To use show multiple variants of a single model: `{"name":"Gemini","file":["Gemini","Gemini Bass"]}`
- To use a different display name ("name") and filename ("file"): `{"name":"Carbo Tenore ZH-DX200-CT","file":"Tenore"}`
- To use show multiple variants of a single model: `{"name":"Gemini","file":["Gemini","Gemini Bass"]}`

The full list of options is as follows:

* "name" is the displayed model name.
* "collab" gives the name of a collaborator. If that collaborator is on
- "name" is the displayed model name.
- "collab" gives the name of a collaborator. If that collaborator is on
the list of brands, the headphone will be categorized under both the
main vendor and the collaborator.
* "file" gives either a single filename or a list. If a list is given,
- "file" gives either a single filename or a list. If a list is given,
then "name" is used only to for the headphone's name in the selection
menu. The key will use filenames for display unless one of the following
options is specified.
* "suffix" is a list with the same length as the list of files. The
display name is the model name plus the variant's suffix. So , {"name":"R3","file":["R3","R3 C"],"suffix":["","Custom"]} ]
- "suffix" is a list with the same length as the list of files. The
display name is the model name plus the variant's suffix. So , {"name":"R3","file":["R3","R3 C"],"suffix":["","Custom"]} ]
`{"name":"R3","file":["R3","R3 C"],"suffix":["","Custom"]}` uses files
based on the names `R3` and `R3 C` but shows the names "R3" and
"R3 Custom".
* "prefix" is some string that should appear at the start of each
- "prefix" is some string that should appear at the start of each
filename. The display name is then the filename, except that if the
prefix appears at the start of the filename it is replaced with the
display name. So
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM node:23.11-alpine3.21

RUN npm install --global pnpm@^10.10.0

WORKDIR /lab
21 changes: 12 additions & 9 deletions Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ Most parts of the interface are arranged using flexboxes, and rearranged
with CSS media queries to detect screen width and aspect ratio.

There are three main layouts:
* The desktop layout places the graph window at the top with the selector and manager side by side below it.
* The mobile layout (for narrow screens) stacks everything vertically with the selector above the manager.
* When the screen is very wide relative to its height, the selector and manager are stacked as in the mobile layout but placed right of the graph window.

- The desktop layout places the graph window at the top with the selector and manager side by side below it.
- The mobile layout (for narrow screens) stacks everything vertically with the selector above the manager.
- When the screen is very wide relative to its height, the selector and manager are stacked as in the mobile layout but placed right of the graph window.

If the screen is narrow enough, the toolbar below the graph window will
collapse to avoid clutter. The entire toolbar can be shown by clicking
Expand Down Expand Up @@ -120,6 +121,7 @@ natural spline tends to emphasize little bumps in the data, making it
worse even than linear interpolation.

Mathematically, a smoothing spline minimizes a weighted sum of:

1. All the square differences between the original and smoothed values, and
2. The integral of the square of the second derivative of the smoothed function.

Expand Down Expand Up @@ -209,7 +211,7 @@ indicate how they might correspond. CrinGraph weights graphs using the
[ISO 226:2003](https://en.wikipedia.org/wiki/Equal-loudness_contour)
loudness standard (with linear rather than cubic interpolation, since it
has little effect on the average) with
[free field](https://en.wikipedia.org/wiki/Free_field_(acoustics))
[free field](<https://en.wikipedia.org/wiki/Free_field_(acoustics)>)
compensation (which most closely matches the conditions in which that
standard was measured) to convert from speakers to IEMs. The flat bass
response of the free field compensation is set to -7 dB to produce a
Expand Down Expand Up @@ -303,8 +305,8 @@ be skipped until a better one is found, giving up after three tries.

[Martin Ankerl](https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/)
describes a method which selects hues with spacing based on the golden
ratio. Spacing in this way gives a one-dimensional *low-discrepancy
sequence*: a sequence in which it takes a while for values similar to
ratio. Spacing in this way gives a one-dimensional _low-discrepancy
sequence_: a sequence in which it takes a while for values similar to
previous ones to appear. CrinGraph extends this technique to the three
dimensions of the
[HCL color space](https://en.wikipedia.org/wiki/HCL_color_space)—hue,
Expand All @@ -324,9 +326,10 @@ cross-section along the ring, like a thick washer. Three modifications
are made to this ring in order to account for human perception, or maybe
imperfect perceptual uniformity of HCL space, or even unsuitability for
lines rather than color fields.
* Hues are shifted so cool colors like blues and greens appear less often, and reds and yellows more often.
* Hues are shifted towards six colors with evenly spaced hues—the primary and secondary colors red, yellow, green, cyan, blue, and purple.
* Chroma and luminance are shifted so that yellows are brighter and bolder, and blues darker.

- Hues are shifted so cool colors like blues and greens appear less often, and reds and yellows more often.
- Hues are shifted towards six colors with evenly spaced hues—the primary and secondary colors red, yellow, green, cyan, blue, and purple.
- Chroma and luminance are shifted so that yellows are brighter and bolder, and blues darker.

Channels are separated from one another primarily by adjusting hue and
chroma. Channels with different luminance don't look related. The
Expand Down
Loading