New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

freqi

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

freqi - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

10

demo/app.js

@@ -36,2 +36,8 @@ 'use strict';

const scaleConfigTruePythagOpts = {
startFreq: cNoteFreq,
intervals: [0, 12, 24, 36, 48],
mode: 'truePythag'
};
const scaleFrequencies = freqi.getFreqs(scaleConfigAllOpts);

@@ -41,2 +47,3 @@ // const scaleFrequencies = freqi.getFreqs(scaleConfigMandatoryOpts);

// const scaleFrequencies = freqi.getFreqs(scaleConfigHSeriesOpts);
// const scaleFrequencies = freqi.getFreqs(scaleConfigTruePythagOpts);
console.log('scaleFrequencies', scaleFrequencies);

@@ -64,2 +71,3 @@

function playSineCb(scale) {
console.log(scale[index]);
playSine(scale[index]);

@@ -89,3 +97,3 @@ if (index >= scale.length - 1) {

if (!connected) {
play(scaleFrequencies, 1000);
play(scaleFrequencies, 2000);
}

@@ -92,0 +100,0 @@ console.log('connected', connected);

@@ -14,2 +14,3 @@ (function (global, factory) {

var H_SERIES_STR = 'hSeries';
var TRUE_PYTHAG = 'truePythag';
var CHROMATIC_SCALE = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];

@@ -267,10 +268,10 @@ var justTuningSystems = {

*/
function getAllOctaveJustIntervals(interval, justIntervalsArr) {
function getAllOctaveJustIntervals(interval, justIntervalsArrLength) {
var _intervalAbs = Math.abs(interval);
var _mult = _intervalAbs / justIntervalsArr.length;
var _mult = _intervalAbs / justIntervalsArrLength;
var _multFloor = Math.floor(_mult);
var _inRangeIndex = _intervalAbs - (_multFloor * justIntervalsArr.length);
var _negIndex = justIntervalsArr.length - _inRangeIndex;
var _inRangeIndex = _intervalAbs - (_multFloor * justIntervalsArrLength);
var _negIndex = justIntervalsArrLength - _inRangeIndex;
var _multF;
if (_intervalAbs % justIntervalsArr.length === 0) {
if (_intervalAbs % justIntervalsArrLength === 0) {
return {

@@ -284,3 +285,3 @@ mult: _mult,

if (_isPos) {
_newInterval = interval - (_multFloor * justIntervalsArr.length);
_newInterval = interval - (_multFloor * justIntervalsArrLength);
_multF = _multFloor;

@@ -297,2 +298,57 @@ }

}
function raiseOrReduceByFifth(number, _up) {
var upperFifthRatio = 3 / 2;
var lowerFifthRatio = 2 / 3;
if (_up) {
return number * upperFifthRatio;
}
return number * lowerFifthRatio;
}
function multOrDivide(_number, _mult, _up) {
if (_up) {
return _number / _mult;
}
return _number * _mult;
}
function getCorrectIndex(interval, _up, notesInOctave, mult) {
var step = 5;
var multOffset = _up ? mult : mult - 1;
var oct = multOffset * notesInOctave;
var result = notesInOctave;
var prevNum = result;
var actInterval = Math.abs(interval);
for (var index = 0; index < actInterval; index++) {
result = prevNum - step;
prevNum = result;
if (result < 0) {
result = notesInOctave - Math.abs(result);
prevNum = result;
}
}
return result + oct;
}
function getPythagNoteWithinOct(index, notesInOctave, noteFreq, _up) {
var halfOctave = notesInOctave / 2;
var rangeInterval = getAllOctaveJustIntervals(index, notesInOctave).rangeInterval;
if (rangeInterval < halfOctave && index % 2 !== 0 || rangeInterval >= halfOctave && index % 2 === 0) {
return multOrDivide(noteFreq, 2, _up);
}
return noteFreq;
}
function getTruePythagNote(eTNoteConfig, _up) {
if (eTNoteConfig.interval === 0) {
return eTNoteConfig.startFreq;
}
var notesInOctave = 12;
var mult = getAllOctaveJustIntervals(eTNoteConfig.interval, notesInOctave).mult;
var correctIndex = getCorrectIndex(eTNoteConfig.interval, _up, notesInOctave, mult);
var noteFreq = eTNoteConfig.startFreq;
var prevNote = noteFreq;
for (var index = 0; index < correctIndex; index++) {
noteFreq = raiseOrReduceByFifth(prevNote, _up);
noteFreq = getPythagNoteWithinOct(index, notesInOctave, noteFreq, _up);
prevNote = noteFreq;
}
return noteFreq;
}
function getHSeriesNote(eTNoteConfig, _up) {

@@ -328,3 +384,3 @@ var interval;

var _justIntervalsArr = justTuningSystems[eTNoteConfig.mode];
var _rangeObj = getAllOctaveJustIntervals(eTNoteConfig.interval, _justIntervalsArr);
var _rangeObj = getAllOctaveJustIntervals(eTNoteConfig.interval, _justIntervalsArr.length);
var _ratioFraction = _justIntervalsArr[_rangeObj.rangeInterval][0] / _justIntervalsArr[_rangeObj.rangeInterval][1];

@@ -366,2 +422,5 @@ var _multiplier = Math.pow(2, _rangeObj.mult);

}
else if (eTNoteConfig.mode === TRUE_PYTHAG) {
_note = getTruePythagNote(eTNoteConfig, _up);
}
else {

@@ -491,5 +550,10 @@ _note = getJustIntNote(eTNoteConfig, _up, justTuningSystems);

addMissingNotesFromInterval: addMissingNotesFromInterval,
getCorrectIndex: getCorrectIndex,
raiseOrReduceByFifth: raiseOrReduceByFifth,
multOrDivide: multOrDivide,
getSingleFreq: getSingleFreq,
getJustIntNote: getJustIntNote,
getHSeriesNote: getHSeriesNote,
getTruePythagNote: getTruePythagNote,
getPythagNoteWithinOct: getPythagNoteWithinOct,
getAllOctaveJustIntervals: getAllOctaveJustIntervals,

@@ -496,0 +560,0 @@ getModes: getModes,

2

package.json
{
"name": "freqi",
"version": "1.2.0",
"version": "1.3.0",
"description": "A library that generates musical frequencies for use with the Web Audio API",

@@ -5,0 +5,0 @@ "main": "freqi.js",

@@ -14,6 +14,6 @@ # Freqi

* Return actual sonic frequencies in Hz or relative frequencies for use with audio files
* NEW: Return frequencies from different tuning systems
* Allow for any number of semitones per octave - Equal Temperament mode only
* NEW: Support multiple tuning systems, in particular equal temperament and just intonation
* Allow for any number of semitones per octave - equal temperament mode only
* Return an array of frequencies of any length
* Provide a way of creating frequencies from within the intervals
* Provide a way of creating frequencies from within the intervals themselves
* Handle bad data

@@ -32,9 +32,2 @@

## Demo
[View the online demo on GitHub here](https://rjbultitude.github.io/freqi/demo/index.html)
Or download/clone it and run `npm install` which will install any dependencies, `npm run build` to create the demo bundle and `npm run start` which will start a new server at localhost:8080.
Then, be sure to navigate to the demo folder in order to see the page i.e. localhost:8080/demo
## Getting Started

@@ -68,18 +61,26 @@

`intervals` is the set of notes you want to generate frequencies from. These intervals can be any integer, positive or negative e.g. `[-5, 0, 7]`.
`intervals` is the set of notes you want to generate frequencies from. These intervals can be any integer, positive or negative e.g. `[-5, 0, 7]` where `0` is the start frequency.
`startFreq` can be a frequency in Hz, such as `440` (for the note A) or a relative frequency such `1` which is useful for playing back audio files, such as MP3s or OGGs, where `1` is the original playback rate. 440 is the default value.
`startFreq` can be a frequency in Hz, such as `440` (for the note A) or a relative frequency such `1` which is useful for playing back audio files, such as MP3s or OGGs, where `1` is the original playback rate. `440` is the default value.
**NEW**
Freqi now supports Just Intonation tuning systems. By default it will use equal temperament, but to use a Just tuning system set the `mode` to one of the following:
* `pythagorean`
**NEW | Tuning Systems**
Freqi now supports just intonation tuning systems. By default it will use equal temperament, but to use a Just tuning system set the `mode` to one of the following:
* `pythagorean` - tempered pythagorean
* `truePythagorean` - all notes are calculated using fifths (3/2), which introduces the [pyhthagorean comma](https://en.wikipedia.org/wiki/Pythagorean_comma)
* `fiveLimit`
* `diatonic`
* `diatonic` - this system has only 7 notes per octave
* `diatonicIndian`
* `twentyTwoShrutis`
* `gioseffoZarlino`
Once in one of these modes other config params, such as `numNotes`, will have no effect as they are fixed scale systems.
Technically speaking, these Just tuning systems are actually tempered as upper and lower octaves are acheived by increasing or decreasing their frequencies by a power of 2. However, the notes in the first octave of each tuning system use the correct ratios. The object containing the ratios for each system is exported as `justTuningSystems` should you need to view it. If you want to list all the keys use the method `getModes`.
* `twentyTwoShrutis` - as the name suggests, there are 22 notes per octave
* `gioseffoZarlino` - there are 16 notes per octave
Once in one of these modes, other config params, such as `numNotes`, will have no effect as they are fixed scale systems.
Technically speaking, most of the just tuning systems are actually tempered in that the upper and lower octaves are acheived by increasing or decreasing their frequencies by a power of 2. The object containing the ratios for each system is exported as `justTuningSystems` should you need to view it. If you want to list all the tuning system keys, use the method `getModes`.
There is also a mode for the harmonic series `hSeries`, though in its raw state it's not particularly useful for making music, but may be of interest to music theorists.

@@ -114,4 +115,15 @@

## Demo
[View the online demo on GitHub here](https://rjbultitude.github.io/freqi/demo/index.html)
Or download/clone it and run `npm install` which will install any dependencies, `npm run build` to create the demo bundle and `npm run start` which will start a new server at localhost:8080.
Then, be sure to navigate to the demo folder in order to see the page i.e. localhost:8080/demo
## Release notes
1.3.0 Support for true pythagorean scale added.
1.2.0 Support for Gioseffo Zarlino's 16 note scale added.
1.1.0 As described above, 1.1.0 supports mutliple tuning systems. The source has been refactored to TypeScript and test coverage has been improved.

@@ -118,0 +130,0 @@

@@ -52,5 +52,11 @@ /*

interface AllOctaveJustIntervals {
mult: number;
rangeInterval: number;
}
// Constants
const EQ_TEMP_STR = 'eqTemp';
const H_SERIES_STR = 'hSeries';
const TRUE_PYTHAG = 'truePythag';
const CHROMATIC_SCALE: Array<string> = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];

@@ -324,10 +330,10 @@ const justTuningSystems: JustTuningSystems = {

*/
function getAllOctaveJustIntervals(interval: number, justIntervalsArr: Array): object {
function getAllOctaveJustIntervals(interval: number, justIntervalsArrLength: number): AllOctaveJustIntervals {
const _intervalAbs = Math.abs(interval);
const _mult = _intervalAbs / justIntervalsArr.length;
const _mult = _intervalAbs / justIntervalsArrLength;
const _multFloor = Math.floor(_mult);
const _inRangeIndex = _intervalAbs - (_multFloor * justIntervalsArr.length);
const _negIndex = justIntervalsArr.length - _inRangeIndex;
const _inRangeIndex = _intervalAbs - (_multFloor * justIntervalsArrLength);
const _negIndex = justIntervalsArrLength - _inRangeIndex;
let _multF;
if (_intervalAbs % justIntervalsArr.length === 0) {
if (_intervalAbs % justIntervalsArrLength === 0) {
return {

@@ -341,3 +347,3 @@ mult: _mult,

if (_isPos) {
_newInterval = interval - (_multFloor * justIntervalsArr.length);
_newInterval = interval - (_multFloor * justIntervalsArrLength);
_multF = _multFloor;

@@ -355,2 +361,62 @@ } else {

function raiseOrReduceByFifth(number: number, _up: boolean): number {
const upperFifthRatio = 3/2;
const lowerFifthRatio = 2/3;
if (_up) {
return number * upperFifthRatio;
}
return number * lowerFifthRatio;
}
function multOrDivide(_number: number, _mult: number, _up: boolean): number {
if (_up) {
return _number / _mult;
}
return _number * _mult;
}
function getCorrectIndex(interval: number, _up: boolean, notesInOctave: number, mult: number): number {
const step = 5;
const multOffset = _up ? mult : mult - 1;
const oct = multOffset * notesInOctave;
let result = notesInOctave;
let prevNum = result;
const actInterval = Math.abs(interval);
for (let index = 0; index < actInterval; index++) {
result = prevNum - step;
prevNum = result;
if (result < 0) {
result = notesInOctave - Math.abs(result);
prevNum = result;
}
}
return result + oct;
}
function getPythagNoteWithinOct(index, notesInOctave, noteFreq, _up): number {
const halfOctave = notesInOctave / 2;
const { rangeInterval } = getAllOctaveJustIntervals(index, notesInOctave);
if (rangeInterval < halfOctave && index % 2 !== 0 || rangeInterval >= halfOctave && index % 2 === 0) {
return multOrDivide(noteFreq, 2, _up);
}
return noteFreq;
}
function getTruePythagNote(eTNoteConfig: ETNoteConfig, _up): number {
if (eTNoteConfig.interval === 0) {
return eTNoteConfig.startFreq;
}
const notesInOctave = 12;
const { mult } = getAllOctaveJustIntervals(eTNoteConfig.interval, notesInOctave);
const correctIndex = getCorrectIndex(eTNoteConfig.interval, _up, notesInOctave, mult);
let noteFreq = eTNoteConfig.startFreq;
let prevNote = noteFreq;
for (let index = 0; index < correctIndex; index++) {
noteFreq = raiseOrReduceByFifth(prevNote, _up);
noteFreq = getPythagNoteWithinOct(index, notesInOctave, noteFreq, _up);
prevNote = noteFreq;
}
return noteFreq;
}
function getHSeriesNote(eTNoteConfig: ETNoteConfig, _up): number {

@@ -387,3 +453,3 @@ let interval;

const _justIntervalsArr = justTuningSystems[eTNoteConfig.mode];
const _rangeObj = getAllOctaveJustIntervals(eTNoteConfig.interval, _justIntervalsArr);
const _rangeObj = getAllOctaveJustIntervals(eTNoteConfig.interval, _justIntervalsArr.length);
const _ratioFraction = _justIntervalsArr[_rangeObj.rangeInterval][0] / _justIntervalsArr[_rangeObj.rangeInterval][1];

@@ -422,3 +488,6 @@ const _multiplier = Math.pow(2, _rangeObj.mult);

_note = getHSeriesNote(eTNoteConfig, _up);
} else {
} else if (eTNoteConfig.mode === TRUE_PYTHAG) {
_note = getTruePythagNote(eTNoteConfig, _up);
}
else {
_note = getJustIntNote(eTNoteConfig, _up, justTuningSystems);

@@ -545,5 +614,10 @@ }

addMissingNotesFromInterval,
getCorrectIndex,
raiseOrReduceByFifth,
multOrDivide,
getSingleFreq,
getJustIntNote,
getHSeriesNote,
getTruePythagNote,
getPythagNoteWithinOct,
getAllOctaveJustIntervals,

@@ -550,0 +624,0 @@ getModes,

@@ -716,2 +716,7 @@ 'use strict';

};
this.configUp = {
startFreq: 440,
interval: 2,
mode: 'hSeries'
}
});

@@ -728,2 +733,5 @@

});
it('should return the start freq times the interval if _up arg is true', function() {
expect(freqi.getHSeriesNote(this.configUp, true)).to.equal(880);
});
});

@@ -743,21 +751,21 @@

it('should return mult 0 when interval argument is within the array argument length', function() {
expect(freqi.getAllOctaveJustIntervals(2, this.justIntArr).mult).to.equal(0);
expect(freqi.getAllOctaveJustIntervals(2, this.justIntArr.length).mult).to.equal(0);
});
it('should return mult 1 when interval argument is within the next multiple of the array argument length', function() {
expect(freqi.getAllOctaveJustIntervals(6, this.justIntArr).mult).to.equal(1);
expect(freqi.getAllOctaveJustIntervals(6, this.justIntArr.length).mult).to.equal(1);
});
it('should return mult 2 when interval argument is double the array argument length', function() {
expect(freqi.getAllOctaveJustIntervals(10, this.justIntArr).mult).to.equal(2);
expect(freqi.getAllOctaveJustIntervals(10, this.justIntArr.length).mult).to.equal(2);
});
it('should return mult 2 when interval argument is between double and treble the array argument length', function() {
expect(freqi.getAllOctaveJustIntervals(13, this.justIntArr).mult).to.equal(2);
expect(freqi.getAllOctaveJustIntervals(13, this.justIntArr.length).mult).to.equal(2);
});
it('should return mult 1 when interval argument is within the array argument length but negative', function() {
expect(freqi.getAllOctaveJustIntervals(-2, this.justIntArr).mult).to.equal(1);
expect(freqi.getAllOctaveJustIntervals(-2, this.justIntArr.length).mult).to.equal(1);
});
it('should return mult 2 when interval argument is double the array argument length but negative', function() {
expect(freqi.getAllOctaveJustIntervals(-10, this.justIntArr).mult).to.equal(2);
expect(freqi.getAllOctaveJustIntervals(-10, this.justIntArr.length).mult).to.equal(2);
});
it('should return mult 2 when interval argument is between double and treble the array argument length but negative', function() {
expect(freqi.getAllOctaveJustIntervals(-13, this.justIntArr).mult).to.equal(3);
expect(freqi.getAllOctaveJustIntervals(-13, this.justIntArr.length).mult).to.equal(3);
});

@@ -772,12 +780,84 @@ });

it('should return rangeInterval 3 when interval argument is 3', function() {
expect(freqi.getAllOctaveJustIntervals(3, this.justIntArr).rangeInterval).to.equal(3);
expect(freqi.getAllOctaveJustIntervals(3, this.justIntArr.length).rangeInterval).to.equal(3);
});
it('should return rangeInterval 3 when interval argument is greater than the array argument length by three items', function() {
expect(freqi.getAllOctaveJustIntervals(8, this.justIntArr).rangeInterval).to.equal(3);
expect(freqi.getAllOctaveJustIntervals(8, this.justIntArr.length).rangeInterval).to.equal(3);
});
it('should return rangeInterval 4 when interval argument is greater than the array argument length and negative', function() {
expect(freqi.getAllOctaveJustIntervals(-6, this.justIntArr).rangeInterval).to.equal(4);
expect(freqi.getAllOctaveJustIntervals(-6, this.justIntArr.length).rangeInterval).to.equal(4);
});
});
describe('getCorrectIndex', function() {
beforeEach(function() {
this.notesInOct = 12;
this.circleOfFifths = [7, 2, 9, 4, 11, 6, 1, 8, 3, 10, 5];
});
it('should return 7 when interval argument is 1', function() {
expect(freqi.getCorrectIndex(1, true, this.notesInOct, 0)).to.equal(7);
});
it('should return 7 + notesInOct when interval argument is 13', function() {
expect(freqi.getCorrectIndex(13, true, this.notesInOct, 1)).to.equal(19);
});
});
describe('raiseOrReduceByFifth', function() {
it('should return number times 1.5 if _up arg is true', function() {
expect(freqi.raiseOrReduceByFifth(1, true)).to.equal(1.5);
});
it('should return number divided 1.5 if _up arg is false', function() {
expect(freqi.raiseOrReduceByFifth(3, false)).to.equal(2);
});
});
describe('multOrDivide', function() {
it('should divide num arg by mult arg if _up arg is true', function() {
expect(freqi.multOrDivide(2, 2, true)).to.equal(1);
});
it('should multiply num arg by mult arg if _up arg is false', function() {
expect(freqi.multOrDivide(2, 2, false)).to.equal(4);
});
});
describe('getPythagNoteWithinOct', function() {
it('should divide freq arg by 2 arg if interval arg is odd and less than half of notesInOct and _up arg is true', function() {
expect(freqi.getPythagNoteWithinOct(3, 12, 440, true)).to.equal(220);
});
it('should multiply freq arg by 2 arg if interval arg is odd and less than half of notesInOct and _up arg is false', function() {
expect(freqi.getPythagNoteWithinOct(3, 12, 440, false)).to.equal(880);
});
it('should divide freq arg by 2 arg if interval arg is even and greater than half of notesInOct and _up arg is true', function() {
expect(freqi.getPythagNoteWithinOct(8, 12, 440, true)).to.equal(220);
});
it('should multiply freq arg by 2 arg if interval arg is even and greater than half of notesInOct and _up arg is false', function() {
expect(freqi.getPythagNoteWithinOct(8, 12, 440, false)).to.equal(880);
});
});
describe('getTruePythagNote', function() {
beforeEach(function() {
this.config = {
startFreq: 261.6,
interval: 0
};
this.configGNote = {
startFreq: 261.6,
interval: 7
};
this.configLowerFNote = {
startFreq: 261.6,
interval: -7
};
});
it('should return the start freq if interval is zero', function() {
expect(freqi.getTruePythagNote(this.config, true)).to.equal(261.6);
});
it('should return the start freq * 1.5 if interval is seven', function() {
expect(freqi.getTruePythagNote(this.configGNote, true)).to.equal(261.6 * 1.5);
});
it('should return the start freq / 1.5 if interval is minus seven', function() {
expect(freqi.getTruePythagNote(this.configLowerFNote, false)).to.equal(261.6 / 1.5);
});
});
describe('getModes', function() {

@@ -784,0 +864,0 @@ it('should return an array the length of justTuningSystems plus the default (eqTemp) and the harmonic series', function() {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc