Skip to content

Repository files navigation

Programming language Version CI - production CI - development Tested with Jest

Chord Finder 🎹

Chord Finder is a JavaScript web application that identifies the chord you are playing on the piano, including inversions. Click the piano keys or use the mapped computer-keyboard controls to build a chord. Select two notes to identify the interval between them.

I started by rewriting my previous C++ chord finder console application in JavaScript and added the web interface as I went.

View Web Application

Chord Finder app demo

Event Handlers

Code is triggered by clicking or pressing keys on the keyboard UI. The example assumes index.js has already initialized userChordIds and preloaded the note audio with notes = sound.preload().

// mouse click on piano key event
$(".key").click(function () {
	//pass note id to add to chord
	let noteCode = $(this).attr('id')
	$(this).toggleClass("pressed")	//toggle key color key when pressed
	processDOMChord(noteCode, userChordIds, notes)
})

// keyboard keypress event
$("html").keypress(function (element) {
	let noteCode = _computerKeyboardMap.get(element.which)
	$("#" + noteCode).toggleClass("pressed")
	processDOMChord(noteCode, userChordIds, notes)
})

// reset button event
$(".reset").click(function (){
	userChordIds.forEach((v)=>$("#" + v).toggleClass("pressed"))
	userChordIds = []
	processDOMChord(undefined, userChordIds)
})

Unit Testing & Coverage

Using Jest for unit testing. GitHub Actions runs on pushes to, and pull requests targeting, master or development. The workflow uses Node.js 24, runs the tests with coverage, uploads the full coverage report as an artifact, and builds the Browserify bundle. Same-repository pull requests also receive a coverage summary comment.

# clean install the locked dependency versions
npm ci

# run tests with coverage
npm test

# rebuild the browser bundle.js
npm run build

Coverage thresholds are 100% for statements, functions, and lines, with 95% branch coverage. Use npm run jest-watch for an interactive test watcher.

Deployments

The production site is available at mnl.space/Chord-Finder. The production workflow rebuilds the bundle and publishes the master branch contents to GitHub Pages.

Pull requests targeting development or master receive a preview deployment at:

https://www.mnl.space/Chord-Finder/pr-preview/pr-<number>/

The preview workflow runs when a pull request is opened, reopened, updated, or closed. The preview link is added to the pull request using the URL pattern above, and the preview is removed when the pull request closes. Preview deployments are available for pull requests from this repository; forked pull requests are not deployed.

Development Setup

Use a local server to avoid CORS errors when testing sound. The project uses Browserify to bundle the JavaScript files into src/js/bundle.js; VS Code Live Server is one option for serving the project locally.

Use Node.js 24 and npm to match the CI environment. The repository's lockfile keeps dependency versions consistent, so install dependencies with npm ci rather than relying on a globally installed tool or an unpinned npx package.

# download the repo locally from github and cd into the folder
gh repo clone ManuelVargas1251/Chord-Finder
cd Chord-Finder

# install the locked dependencies, including Browserify
npm ci

# rebuild the bundle after changing JavaScript files
npm run build

Application Architecture

%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '12px', 'primaryTextColor': '#172033', 'lineColor': '#64748b'}, 'flowchart': {'nodeSpacing': 24, 'rankSpacing': 30, 'padding': 8}}}%%
flowchart TB
	user((User)) --> events["index.js<br/>Keyboard and click handlers"]
	events --> process["processDOMChord.js<br/>Validate, toggle, and sort notes"]

	subgraph inputWork["Input processing"]
		direction TB
		process -->|valid note| sound["sound.js<br/>Preload and play note"]
		process --> noteNames["getNoteChord.js<br/>Convert note IDs to names"]
	end

	process --> update["updateChord.js<br/>Build chord result"]
	process -->|reset| update

	subgraph analysis["Chord analysis"]
		direction TB
		update --> intervals["getUserIntervals.js<br/>Calculate adjacent intervals"]
		intervals --> interval["getInterval.js<br/>Measure distance between notes"]
		intervals --> noteId["getNoteId.js<br/>Resolve note names to IDs"]
		intervals --> chord["getChord.js<br/>Match intervals to a chord"]
	end

	noteNames --> update
	chord --> display[".chord element<br/>Display chord name"]
	update --> display

	classDef inputStyle fill:#fff7ed,stroke:#ea580c,color:#172033
	classDef analysisStyle fill:#e8f1ff,stroke:#2563eb,color:#172033
	classDef outputStyle fill:#ecfdf5,stroke:#16a34a,color:#172033
	class user,events,process,sound,noteNames inputStyle
	class update,intervals,interval,noteId,chord analysisStyle
	class display outputStyle
	style inputWork fill:#fffbeb,stroke:#d97706,color:#172033
	style analysis fill:#eff6ff,stroke:#2563eb,color:#172033
Loading

The canonical Mermaid source is also available separately. The static image is available as a fallback for clients that do not render Mermaid diagrams.

View static chart fallback

Chord Finder application architecture

Environments

By using https://raw.githack.com/ I created working lower environments to test code in any committed branch. The CI badges above report the latest GitHub Actions status separately for master and development.

Production

Development

Reference

Musical Chord Wiki

Musical Interval Wiki

Eleventh Interval Wiki

Octave Interval Wiki

About

🎹🎡 Client web application to find chords through keyboard UI

Topics

Resources

Stars

22 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages