Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
31fdffb
Merge branch 'noramorsi/handlers'
Feb 23, 2022
f03a213
Buggy alternative way to do slope
Feb 23, 2022
0e18f8c
Added a slope demo that plays a tone representing the current slope
Mar 6, 2022
e26230b
jen's in-progress code
Mar 9, 2022
bb45ddf
partial bug fix.
venkateshpotluri Mar 9, 2022
507e051
commitment for venkatesh
Mar 14, 2022
1977415
Merge branch 'origin/jen-architecting' of https://github.com/make4all…
Mar 14, 2022
13d55f6
basic set up of keyboard page; onclick not triggering
noramorsi Mar 25, 2022
add2387
set up space in page for focus
noramorsi Mar 25, 2022
2ea1731
mapping created
noramorsi Mar 27, 2022
ae41e2d
tones playing, need to fix auto-play
noramorsi Mar 27, 2022
6d02a38
attempt at fixing tones continuing
noramorsi Mar 27, 2022
01572c8
basic keyboard visual set up, no change visually
noramorsi Mar 29, 2022
cbcffaf
note ends when key up
noramorsi Mar 29, 2022
6e92b06
style changes
noramorsi Mar 29, 2022
629c684
black keys added, do not wrap like white keys
noramorsi Mar 29, 2022
add9735
shifted down an octave
noramorsi Mar 29, 2022
08c1832
single octave with black keys included
noramorsi Apr 2, 2022
80a44fd
cleaning up constants
noramorsi Apr 2, 2022
0df7913
mouse position sonification demo added
noramorsi Apr 2, 2022
9884cb9
expanded to include 3rd octave
noramorsi Apr 4, 2022
31f8c2d
buggy running average code.
venkateshpotluri Apr 5, 2022
af41f7e
debugging logs.
venkateshpotluri Apr 5, 2022
06ae208
almost done piano.
venkateshpotluri Apr 6, 2022
98467ef
Created a new path /DemoCopyStream with button to copy data collected…
dhruvkhanna38 May 27, 2023
946db22
feature: CopyToClipboardHandler add to dashboard.tsx
dhruvkhanna38 Jun 6, 2023
30e2568
Merge branch 'noramorsi/keyboard' into dhruvkhanna/code-cleanup
dhruvkhanna38 Jun 9, 2023
ca27c18
Merge branch 'origin/jen-architecting' into dhruvkhanna/code-cleanup
dhruvkhanna38 Jun 9, 2023
86bf3ed
fix: build
dhruvkhanna38 Jun 9, 2023
53e1c22
Merge branch 'dhruvkhanna/demo-copy-stream' into dhruvkhanna/code-cle…
dhruvkhanna38 Jun 14, 2023
8cbe2f8
merging noramorsi/keyboard and jen-architecting to main
dhruvkhanna38 Jun 14, 2023
ff48ee5
fix: Dashboard.tsx Cleanup
dhruvkhanna38 Jun 14, 2023
cf517b9
fix: Deleting Copy Handler
dhruvkhanna38 Jun 15, 2023
a1288c2
Updating comments and removing deprecated code
dhruvkhanna38 Oct 9, 2023
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@types/node": "^16.11.6",
"d3": "^7.1.1",
"jacdac-ts": "^1.24.20",
"react-copy-to-clipboard": "^5.1.0",
"react-jacdac": "^1.1.3",
"rxjs": "^7.5.2",
"rxjs-spy": "^8.0.2",
Expand Down
20 changes: 19 additions & 1 deletion src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const MicrobitController = lazy(() => import('./pages/MicrobitController'))

import { HashRouter, Routes, Route } from 'react-router-dom'
import Index from './pages/Index'

import { Keyboard } from './pages/Keyboard'
import { MouseDemo } from './pages/MouseDemo'
if (module.hot) {
module.hot.accept()
}
Expand All @@ -17,6 +18,7 @@ ReactDOM.render(
<Routes>
<Route path="/" element={<Index />} />
<Route path="basic" element={<Demo />} />
,
<Route
path="jacdac"
element={
Expand All @@ -41,6 +43,22 @@ ReactDOM.render(
</Suspense>
}
/>
<Route
path="keyboard"
element={
<Suspense fallback={null}>
<Keyboard />
</Suspense>
}
/>
<Route
path="mousedemo"
element={
<Suspense fallback={null}>
<MouseDemo />
</Suspense>
}
/>
</Routes>
</HashRouter>,
document.getElementById('root'),
Expand Down
295 changes: 5 additions & 290 deletions src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as d3 from 'd3'

import { bus } from '../bus'

import { JDRegister, JDService, REPORT_UPDATE, SoundLevelReg, TraceRecorder } from 'jacdac-ts'
import { REPORT_UPDATE, SoundLevelReg, TraceRecorder } from 'jacdac-ts'
import { JacdacProvider, useServices, useChange, useBus } from 'react-jacdac'

import {
Expand Down Expand Up @@ -45,67 +45,13 @@ import { Close } from '@mui/icons-material'
import DataHandlerItem from '../views/dashboard/DataHandlerItem'
import JDServiceItem from '../views/dashboard/JDServiceItem'

import { DataHandler } from '../sonification/handler/DataHandler'
import { DatumOutput } from '../sonification/output/DatumOutput'

import { NoteSonify } from '../sonification/output/NoteSonify'
import { NoiseSonify } from '../sonification/output/NoiseSonify'
import { Speech } from '../sonification/output/Speech'
import { NoteHandler } from '../sonification/handler/NoteHandler'
import { OutputStateChange } from '../sonification/OutputConstants'
import { Datum } from '../sonification/Datum'
import { FilterRangeHandler } from '../sonification/handler/FilterRangeHandler'
import { RunningExtremaHandler } from '../sonification/handler/RunningExtremaHandler'
import { SlopeParityHandler } from '../sonification/handler/SlopeParityHandler'
import { FileOutput } from '../sonification/output/FileOutput'
import { SimpleDataHandler } from '../sonification/handler/SimpleDataHandler'

export interface JDServiceWrapper {
name: string
id: string
serviceObject?: JDService
values: JDValueWrapper[]
}

export interface JDValueWrapper {
name: string
id: string
index: number
sinkId: number
domain: [number, number]
units: string
format: (value: number) => string
register: JDRegister
dataHandlers: DataHandlerWrapper[]
unsubscribe?: () => void
}
import { AVAILABLE_DATA_HANDLER_TEMPLATES } from './templates/DataHandlerTemplates'
import { JDServiceWrapper } from './templates/JDInterfaces'

export interface DataHandlerWrapper {
name: string
id: string
description: string
dataOutputs: DataOutputWrapper[]
handlerObject?: DataHandler
createHandler: (domain: [number, number]) => DataHandler
unsubscribe?: () => void
parameters?: ParameterWrapper[]
}

export interface DataOutputWrapper {
name: string
id: string
createOutput: () => DatumOutput
outputObject?: DatumOutput
parameters?: ParameterWrapper[]
}

export interface ParameterWrapper {
name: string
type: string
default?: (obj?: DataHandler | DatumOutput) => number
values?: { display: string; value: number }[]
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => void
}
import { DataHandlerWrapper } from './templates/DataHandlerInterfaces'

export enum PlaybackState {
PlayingLive,
Expand All @@ -126,237 +72,6 @@ const SRV_INFO_MAP = {
[SRV_TEMPERATURE]: { values: [''], units: '°C', format: d3.format('.1f'), domain: [-20, 60] },
}

export const AVAILABLE_DATA_OUTPUT_TEMPLATES = {
note: {
name: 'Note',
id: `Note-${Math.floor(Math.random() * Date.now())}`,
createOutput: () => new NoteSonify(),
parameters: [
{
name: 'Stereo Pan',
type: 'list',
default: (obj?: DataHandler | DatumOutput) => 0,
values: [
{ display: 'Both', value: 0 },
{ display: 'Left', value: -1 },
{ display: 'Right', value: 1 },
],
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const ns = obj as NoteSonify
ns.stereoPannerNode.pan.value = value
}
},
},
],
},
noise: {
name: 'White Noise',
id: `White Noise-${Math.floor(Math.random() * Date.now())}`,
createOutput: () => new NoiseSonify(),
},
earcon: {
name: 'Earcon',
id: `Earcon-${Math.floor(Math.random() * Date.now())}`,
createOutput: () => {
const fo = new FileOutput()
// Use long beep as the default
fetch(`./assets/shortbeep.wav`)
.then((res) => res.arrayBuffer())
.then((buffer: ArrayBuffer) => {
fo.buffer = buffer
})
return fo
},
parameters: [
{
name: 'Earcon to Play',
type: 'list',
default: (obj?: DataHandler | DatumOutput) => 0,
values: [
{ display: 'Short Beep', value: 0 },
{ display: 'Long Beep', value: 1 },
{ display: 'Bell', value: 2 },
{ display: 'Whistle Up', value: 3 },
{ display: 'Whistle Down', value: 4 },
],
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const file_list = [
'shortbeep.wav',
'beep.wav',
'bell.mp3',
'whistle%20up.wav',
'whistle%20down.wav',
]
const fo = obj as FileOutput
fetch(`./assets/${file_list[value]}`)
.then((res) => res.arrayBuffer())
.then((buffer: ArrayBuffer) => {
fo.buffer = buffer
})
}
},
},
],
},
speech: {
name: 'Speech',
id: `Speech-${Math.floor(Math.random() * Date.now())}`,
createOutput: () => new Speech(),
parameters: [
{
name: 'Interrupt when new point arrives?',
type: 'list',
default: (obj?: DataHandler | DatumOutput) => 0,
values: [
{ display: 'Yes', value: 0 },
{ display: 'No', value: 1 },
],
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const sp = obj as Speech
sp.polite = value == 1 ? true : false
}
},
}
]
},
}

const initializeDataOutput = (output: DataOutputWrapper): DataOutputWrapper => {
return { ...output, outputObject: output.createOutput() }
}

export const AVAILABLE_DATA_HANDLER_TEMPLATES: DataHandlerWrapper[] = [
{
name: 'Note Handler',
id: `Note Handler-${Math.floor(Math.random() * Date.now())}`,
description: 'Converts data to an audible note range.',
dataOutputs: [initializeDataOutput(AVAILABLE_DATA_OUTPUT_TEMPLATES.note)],
createHandler: (domain: [number, number]) => new NoteHandler(domain),
},
{
name: 'Filter Range Handler',
id: `Filter Range Handler-${Math.floor(Math.random() * Date.now())}`,
description: "Filters data within the provided range. If within range, sent to this handler's outputs.",
dataOutputs: [
initializeDataOutput(AVAILABLE_DATA_OUTPUT_TEMPLATES.noise),
AVAILABLE_DATA_OUTPUT_TEMPLATES.earcon,
],
createHandler: (domain: [number, number]) =>
new FilterRangeHandler([
(domain[1] - domain[0]) * 0.4 + domain[0],
(domain[1] - domain[0]) * 0.6 + domain[0],
]),
parameters: [
{
name: 'Min',
type: 'number',
default: (obj?: DataHandler | DatumOutput) => {
if (obj) {
const frh = obj as FilterRangeHandler
return frh.domain[0]
} else {
return 0.4
}
},
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const frh = obj as FilterRangeHandler
frh.domain = [value, frh.domain[1]]
}
},
},
{
name: 'Max',
type: 'number',
default: (obj?: DataHandler | DatumOutput) => {
if (obj) {
const frh = obj as FilterRangeHandler
return frh.domain[1]
} else {
return 0.6
}
},
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const frh = obj as FilterRangeHandler
frh.domain = [frh.domain[0], value]
}
},
},
],
},
{
name: 'Extrema Handler',
id: `Extrema Handler-${Math.floor(Math.random() * Date.now())}`,
description: 'Finds the new extrema value (maximum and/or minimum) in the data stream.',
dataOutputs: [
AVAILABLE_DATA_OUTPUT_TEMPLATES.earcon,
initializeDataOutput(AVAILABLE_DATA_OUTPUT_TEMPLATES.speech),
],
createHandler: (domain: [number, number]) => new RunningExtremaHandler(),
parameters: [
{
name: 'Extrema to Find',
type: 'list',
default: (obj?: DataHandler | DatumOutput) => 0,
values: [
{ display: 'Maximum and Minimum', value: 0 },
{ display: 'Maximum Only', value: 1 },
{ display: 'Minimum Only', value: -1 },
],
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const reh = obj as RunningExtremaHandler
reh.direction = value
}
},
},
],
},
// { name: 'Outlier Detection Handler', description: 'Description of outlier detection handler' },
// { name: 'Slope Handler', description: 'Description of slope handler', createHandler: () => new Slope() },
{
name: 'Slope Change Handler',
id: `Slope Change Handler-${Math.floor(Math.random() * Date.now())}`,
description:
'Finds direction of slope changes in the data stream. When the data goes from increasing to decreasing, and vise-versa.',
dataOutputs: [
AVAILABLE_DATA_OUTPUT_TEMPLATES.earcon,
initializeDataOutput(AVAILABLE_DATA_OUTPUT_TEMPLATES.speech),
],
createHandler: (domain: [number, number]) => new SlopeParityHandler(),
parameters: [
{
name: 'Direction to Find',
type: 'list',
default: (obj?: DataHandler | DatumOutput) => 0,
values: [
{ display: 'Postive and Negative', value: 0 },
{ display: 'Positive Only', value: 1 },
{ display: 'Negative Only', value: -1 },
],
handleUpdate: (value: number, obj?: DataHandler | DatumOutput) => {
if (obj) {
const sph = obj as SlopeParityHandler
sph.direction = value
}
},
},
],
},

{
name: 'Simple Handler',
id: `Simple Handler-${Math.floor(Math.random() * Date.now())}`,
description: 'Outputs the raw data stream without processing.',
dataOutputs: [initializeDataOutput(AVAILABLE_DATA_OUTPUT_TEMPLATES.speech)],
createHandler: (domain: [number, number]) => new SimpleDataHandler(),
},
]

function saveText(name: string, data: string, mimeType?: string) {
if (!mimeType) {
if (/\.(csv|txt)/i.test(name)) mimeType = 'text/plain'
Expand Down Expand Up @@ -546,6 +261,7 @@ export function DashboardView() {
template: DataHandlerWrapper,
) => {
console.log(add, serviceId, valueId, template)

const servicesCopy = services.map((service) => {
if (serviceId === service.id) {
const values = service.values.map((value) => {
Expand Down Expand Up @@ -730,7 +446,6 @@ export function DashboardView() {
type: 'number',
}}
/> */}

</Box>
</Box>
<Box role="region" aria-labelledby="header-configure-add" sx={{ mb: 2, mt: 4 }}>
Expand Down
Loading