diff --git a/.gitignore b/.gitignore index f113a2d..05a68e3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.pem *.crx *.zip +*.bak +*.db nacl-src/pnacl diff --git a/README.md b/README.md index 1f80136..1469e28 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,29 @@ +# Modifications in this fork: + +* Automatically pauses recording if signal is below the squelch threshold. + +* m key mutes audio instantly (recording is not affected). Adjust volute to resume. + +* Signal level is displayed with a bar. Hover mouse to read numerical value. + +* Clicking signal bar sets squelch level. + +* PgDn/PgUp moves through the list of saved preset stations. + +* Shift-PgDn begins (or ends) scanning through preset stations. Scanning stops when signal is above preset squelch level and resumes when signal drops below squelch level for a while. + +* Export/Import preset list includes the squelch setting for each station. + +* Clicking on the "Squelch" heading enters or leaves MONITOR mode, where squelch is temporarily set to zero to monitor frequency. + +* f/F key moves to the frequency display for editing (this is in the original help file, but didn't work). + + # Radio Receiver An application to listen to broadcast FM and AM radio from your Chrome browser or your ChromeBook computer using a $15 USB digital TV tuner. -![Radio Receiver screenshot](image-src/interface.png) +![Radio Receiver screenshot](image-src/interface2.png) ## What is this diff --git a/extension/appconfig.js b/extension/appconfig.js index c0eab5f..37891e5 100644 --- a/extension/appconfig.js +++ b/extension/appconfig.js @@ -34,7 +34,7 @@ function AppConfig() { /** Upconverter. */ upconverter: { enable: false, - frequency: 125000000 + frequency: 99999020 // Peter's up converter }, /** Whether free tuning is enabled. */ freeTuning: false diff --git a/extension/audio.js b/extension/audio.js index bf6b3db..dcb668b 100644 --- a/extension/audio.js +++ b/extension/audio.js @@ -24,6 +24,8 @@ function Player() { var frameno = 0; var wavSaver = null; + + var dampedLevel = 0; var ac = new (window.AudioContext || window.webkitAudioContext)(); var gainNode = ac.createGain ? ac.createGain() : ac.createGainNode(); @@ -38,7 +40,10 @@ function Player() { */ function play(leftSamples, rightSamples, level, squelch) { var buffer = ac.createBuffer(2, leftSamples.length, OUT_RATE); - if (level >= squelch) { + dampedLevel = 0.75 * dampedLevel + .25*level*100; + signalBar.value = Math.floor(dampedLevel); + signalBar.title = signalBar.value; + if ((dampedLevel/100) >= squelch) { buffer.getChannelData(0).set(leftSamples); buffer.getChannelData(1).set(rightSamples); } @@ -50,7 +55,26 @@ function Player() { ac.currentTime + TIME_BUFFER); source.start(lastPlayedAt); if (wavSaver != null) { - wavSaver.writeSamples(leftSamples, rightSamples); + if ((dampedLevel/100) >= squelch) { + wavSaver.writeSamples(leftSamples, rightSamples); + } + } + if (typeof scanPresets == 'undefined') { // proof of concept for preset scanning + scanPresets = false; // not likely to be the way it will be implemented + scanCount = 0; // a test to find the possible problems... + } + if (radio.requestingBlocks > 0) { + return; + } + if ( scanPresets ) { + scanCount++; + if ((dampedLevel/100) > squelch) { + scanCount = -5; // resume scanning after x+n no signal events + } + if ( scanCount > 5 && (level < squelch)) { // scan every n events + interface.nextPreset(); // tweak this parameter if too fast for dongle/decoder + scanCount = 0; + } } } @@ -93,7 +117,7 @@ function Player() { function setVolume(volume) { gainNode.gain.value = volume; } - + return { play: play, setVolume: setVolume, diff --git a/extension/auxwindows.js b/extension/auxwindows.js index 4cd16e3..a368ae2 100644 --- a/extension/auxwindows.js +++ b/extension/auxwindows.js @@ -36,6 +36,7 @@ var AuxWindows = (function() { win.contentWindow['opener'] = window; var modeData = copyObject(band.getMode()); modeData['step'] = band.getStep(); + modeData['squelch'] = squelch; var stationData = { 'frequency': frequency, 'display': band.toDisplayName(frequency, true), @@ -138,7 +139,7 @@ var AuxWindows = (function() { 'width': 700, 'height': 600 }, - 'state': 'maximized', + 'state': 'normal', 'resizable': true }); } diff --git a/extension/help.html b/extension/help.html index 0252bd4..9bcbbea 100644 --- a/extension/help.html +++ b/extension/help.html @@ -69,6 +69,11 @@

Using presets

To switch to a preset, click the preset selection box (7) and choose your new preset. The radio will switch to it immediately.

To delete a preset, switch to it and press the “Remove” button (8).

To change a preset's name, switch to it and click the “Save” button (6). Type the new name and press “Save”.

+

To export a set of presets for loading later, go to “Settings” (12) and +click on the Manage your Presets link.

+

Use the PgUp and PgDn keys to select the previous or next preset station in the list.

+

Hold down the shift key and press PgDn to begin automatic scanning of preset stations. +The scan will pause if the squelch level is exceeded. Each preset can have its own squelch value assigned.

Changing volume and stereo

To change the volume, click on the “loudspeaker” icon (9) and move the slider left and right to decrease or increase the volume. You can also use your mouse wheel on the icon to change volume directly.

@@ -101,7 +106,8 @@

Using Free Tuning

If you have configured an upconverter in the settings window you can enable and disable it here by clicking the “Upconverter” field (5).

-

The “Squelch” setting (6) lets you monitor a frequency without having to hear static when nobody is transmitting. The squelch level is the minimum strength level the signal must reach before you can hear it; if it's set to 0, you'll hear everything.

+

The “Squelch” setting (6) lets you monitor a frequency without having to hear static when nobody is transmitting. The squelch level is the minimum strength level the signal must reach before you can hear it; if it's set to 0, you'll hear everything. +Click on the signal strength display to set the squelch value slightly above the noise level.

Settings

You can change a lot of settings by clicking on the “wrench” icon (12). There you can change several settings:

@@ -124,8 +130,12 @@

Keyboard shortcuts

Space BarTurn radio on/off Up ArrowVolume Up Down ArrowVolume Down +mMute Volume Left ArrowDecrease Frequency Right ArrowIncrease Frequency +PgUpPrevious Preset +PgDnNext Preset +Shift-PgDnScan Preset List <Scan for stations by decreasing frequency >Scan for stations by increasing frequency fEdit frequency diff --git a/extension/interface.css b/extension/interface.css index e5bfc64..dab9154 100644 --- a/extension/interface.css +++ b/extension/interface.css @@ -367,6 +367,27 @@ option { width: 30px; } +.signalDisplay { + bottom: 10px; + left: 10px; + width: 125px; +} + +progress { + left: 0px; + width: 100px; + height: 15px; + border: 1px solid #afd; + background: #343; +// visibility: hidden; +} +progress::-webkit-progress-bar { + background: #343; +} +progress[value]::-webkit-progress-value { + background-image: -webkit-linear-gradient(left, red 0%, orange 70%, yellow 90%, white 100%); +} + .freqMinusButton, .freqPlusButton { position: absolute; top: 0; diff --git a/extension/interface.html b/extension/interface.html index d5414b8..09b8d96 100644 --- a/extension/interface.html +++ b/extension/interface.html @@ -82,11 +82,12 @@
-
Squelch:
+
Squelch:
100
+
diff --git a/extension/interface.js b/extension/interface.js index a0e075a..e42c6e8 100644 --- a/extension/interface.js +++ b/extension/interface.js @@ -33,7 +33,7 @@ function Interface(fmRadio) { * The current band configuration; */ var currentBand = Bands['WW']['FM']; - + var currentSquelch = 0; /** * Updates the UI. */ @@ -262,6 +262,12 @@ function Interface(fmRadio) { function changeVolumeUp() { setVolume(fmRadio.getVolume() + 0.1); } + /** + * Mute volume (change to 0). + */ + function muteVolume() { + setVolume(0.0); + } /** * Changes volume with the mouse wheel. @@ -684,6 +690,78 @@ function Interface(fmRadio) { saveSettings(); update(); } + + /** + * Monitor - open squelch by clicking on "Squelch:" to monitor frequency + * Click again on "MONITOR" to resume stored squelch setting + */ + + function squelchClick() { + var mode = appConfig.state.mode.get(); + if ( Squelch.textContent == 'Squelch:') { + currentSquelch = mode.params.squelch; + fmRadio.setSquelch(0); + squelchDisplay.hidden = true; + Squelch.textContent = 'MONITOR'; + } else { + fmRadio.setSquelch(currentSquelch); + Squelch.textContent = 'Squelch:'; + squelchDisplay.hidden = false; + } + } + + + /** + * Change squelch by clicking on signal strength display. + */ + + function clickChangeSquelch(value){ + changeSquelch(value.offsetX); + } + + /** + * Selects the previous preset in the list. + */ + + function prevPreset(shiftKey){ + if ( presetsBox.length < 3 ) { return; } + signalBar.value = 0; + if ( presetsBox[0].selected || presetsBox[1].selected ) { + presetsBox[presetsBox.length-1].selected = true; + selectPreset(); + } else { + for (i = 0; i < presetsBox.length; i++){ + if ( presetsBox[i].selected ){ + presetsBox[i-1].selected = true; + selectPreset(); + break; + } + } + } + } + + /** + * Selects the next preset in the list. + */ + function nextPreset(shiftKey){ + if ( presetsBox.length < 3 ) { return; } + if ( shiftKey ) { + scanPresets = ! scanPresets; + } + signalBar.value = 0; + if ( presetsBox[presetsBox.length-1].selected ) { + presetsBox[1].selected = true; + selectPreset(); + } else { + for (i = 0; i < presetsBox.length; i++){ + if ( presetsBox[i].selected ){ + presetsBox[i+1].selected = true; + selectPreset(); + break; + } + } + } + } /** * Closes the window. @@ -777,6 +855,12 @@ function Interface(fmRadio) { } if (e.type == 'keydown') { switch (e.keyCode) { + case 33: // PgUp + prevPreset(e.shiftKey); + break; + case 34: // PgDn + nextPreset(e.shiftKey); + break; case 37: frequencyMinus(); break; @@ -809,8 +893,13 @@ function Interface(fmRadio) { case 98: // b switchBand(); break; + case 70: // F case 102: // f - showFrequencyEditor(); + frequencyDisplay.click(); + break; + case 77: // M + case 109: // m + muteVolume(); break; case 80: // P case 112: // p @@ -905,6 +994,7 @@ function Interface(fmRadio) { upconverterDisplay.addEventListener('click', toggleUpconverter); attachDisplayInputEvents(squelchDisplay, squelchInput, changeSquelch); squelchDisplay.addEventListener('mousewheel', changeSquelchWheel); + signalDisplay.addEventListener('click', clickChangeSquelch); freqMinusButton.addEventListener('click', frequencyMinus); freqPlusButton.addEventListener('click', frequencyPlus); scanDownButton.addEventListener('click', scanDown); @@ -917,6 +1007,7 @@ function Interface(fmRadio) { window.addEventListener('message', getMessage); window.addEventListener('keydown', handleShortcut); window.addEventListener('keypress', handleShortcut); + Squelch.addEventListener('mousedown',squelchClick); fmRadio.setInterface(this); fmRadio.setOnError(showErrorWindow); loadSettings(function() { @@ -928,6 +1019,7 @@ function Interface(fmRadio) { return { attach: attach, + nextPreset: nextPreset, update: update }; } diff --git a/extension/presetmanager.js b/extension/presetmanager.js index cd89edf..6cb11e9 100644 --- a/extension/presetmanager.js +++ b/extension/presetmanager.js @@ -80,7 +80,7 @@ function showPresets(table, presets, delPresets, precheck) { var isDouble = preset && delPreset; var line; if (delPreset) { - line = makePresetLine(value, delPreset, i, true, isDouble, precheck); + line = makePresetLine(value, delPreset, i, true, isDouble, true); table.firstElementChild.appendChild(line); } if (preset) { @@ -173,6 +173,9 @@ function makeModeCell(preset) { if (mode['upconvert']) { text += '; upconvert=on'; } + if (mode['squelch']) { + text += '; squelch='+mode['squelch']; + } } td.appendChild(document.createTextNode(text)); return td; diff --git a/extension/radiocontroller.js b/extension/radiocontroller.js index c147ef6..b12881f 100644 --- a/extension/radiocontroller.js +++ b/extension/radiocontroller.js @@ -155,6 +155,10 @@ function RadioController() { function getSquelch() { return squelch; } + + function getRB() { + return requestingBlocks; + } /** * Searches a given frequency band for a station, starting at the @@ -686,6 +690,8 @@ function RadioController() { stopRecording: stopRecording, isRecording: isRecording, setInterface: setInterface, - setOnError: setOnError + setOnError: setOnError, + requestingBlocks: getRB + }; } diff --git a/extension/settings.js b/extension/settings.js index 5d92470..1f3e537 100644 --- a/extension/settings.js +++ b/extension/settings.js @@ -27,7 +27,7 @@ autoGain.checked = settings && settings['autoGain']; gain.value = (settings && settings['gain']) || 0; gain.disabled = autoGain.checked; useUpconverter.checked = settings && settings['useUpconverter']; -upconverterFreq.value = (settings && settings['upconverterFreq']) || 125000000; +upconverterFreq.value = (settings && settings['upconverterFreq']) || 99999020; //Peter's upconverter upconverterFreqInput.className = useUpconverter.checked ? '' : 'invisible'; upconverterFreq.disabled = !useUpconverter.checked; enableFreeTuning.checked = settings && settings['enableFreeTuning']; diff --git a/image-src/interface.png b/image-src/interface.png deleted file mode 100644 index 3910f65..0000000 Binary files a/image-src/interface.png and /dev/null differ diff --git a/image-src/interface2.png b/image-src/interface2.png new file mode 100644 index 0000000..94bebdf Binary files /dev/null and b/image-src/interface2.png differ