Musical keyboard component written in React.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

50 行
1.4 KiB

  1. import * as React from 'react'
  2. import SoundGenerator from '../services/SoundGenerator'
  3. type ChangeProps = {
  4. setChannel(channel: number): void
  5. }
  6. type Change = (props: ChangeProps) => React.ChangeEventHandler<HTMLInputElement>
  7. export const change: Change = ({ setChannel }) => e => {
  8. const { value: rawValue } = e.target
  9. const value = Number(rawValue)
  10. setChannel(value)
  11. }
  12. type KeyChannel = {
  13. key: number,
  14. velocity: number,
  15. channel: number,
  16. }
  17. type KeyChannelCallback = (oldKeys: KeyChannel[]) => KeyChannel[]
  18. type HandleProps = {
  19. setKeyChannels(callback: KeyChannelCallback | KeyChannel[]): void,
  20. generator?: SoundGenerator,
  21. channel: number,
  22. }
  23. type Handle = (props: HandleProps) => (newKeys: KeyChannel[]) => void
  24. export const handle: Handle = ({ setKeyChannels, generator, channel, }) => newKeys => {
  25. setKeyChannels((oldKeys) => {
  26. if (generator! !== undefined) {
  27. const oldKeysKeys = oldKeys.map((k) => k.key)
  28. const newKeysKeys = newKeys.map((k) => k.key)
  29. const keysOff = oldKeys.filter((ok) => !newKeysKeys.includes(ok.key))
  30. const keysOn = newKeys.filter((nk) => !oldKeysKeys.includes(nk.key))
  31. keysOn.forEach((k) => {
  32. generator.noteOn(channel, k.key, Math.floor(k.velocity * 127))
  33. })
  34. keysOff.forEach((k) => {
  35. generator.noteOff(channel, k.key, Math.floor(k.velocity * 127))
  36. })
  37. }
  38. return newKeys
  39. })
  40. }