我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
本文技术栈:React + Antd
布局随便写的,主要是咱不是 UI,就随便整一点居中布局就行。
Button 按钮 + Select 下拉选择框
声音的播放
声音这块主要是通过 AudioContext 来实现的。
AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个AudioNode表示。音频上下文控制它包含的节点的创建和音频处理或解码的执行。在做任何其他操作之前,您需要创建一个AudioContext对象,因为所有事情都是在上下文中发生的。建议创建一个AudioContext对象并复用它,而不是每次初始化一个新的AudioContext对象,并且可以对多个不同的音频源和管道同时使用一个AudioContext对象。
网上搜索钢琴 1234567 对应的频率为
[261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88]
吉他对应的频率为
[329.6276, 246.9417, 195.9977, 146.8324, 110.0000, 82.4069]
获取用户按下按钮对应的按键数字
useEffect(() => {
document.addEventListener("keydown", (e) => {
if (e.key.match(/^\+?[0-6]\d*$/)) {
handleCreate(parseInt(e.key))
}
})
}, [])
handleCreate 是程序的主要处理函数,将获取的 index 传入该函数。
const handleCreate = (index) => {
// 创建音频上下文
const audioCtx = new AudioContext()
// 创建音调控制对象
const oscillator = audioCtx.createOscillator();
// 创建音量控制对象
const gainNode = audioCtx.createGain();
// 音调音量关联
oscillator.connect(gainNode);
// 音量和设备关联
gainNode.connect(audioCtx.destination);
// 音调类型指定为正弦波
oscillator.type = audioTypeList[index.current];
// 设置音调频率
oscillator.frequency.value = audioDataList.current[index];
// 先把当前音量设为0
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
// 0.01秒时间内音量从刚刚的0变成1,线性变化
gainNode.gain.linearRampToValueAtTime(1, audioCtx.currentTime + 0.01);
// 声音走起
oscillator.start(audioCtx.currentTime);
// 1秒时间内音量从刚刚的1变成0.001,指数变化
gainNode.gain.exponentialRampToValueAtTime(0.1, audioCtx.currentTime + 1);
// 1秒后停止声音
oscillator.stop(audioCtx.currentTime + 1)
}
屏幕录音
这个主要通过 mediaDevices.getDisplayMedia 来实现。
MediaDevices.getUserMedia()会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其它轨道类型。
MediaRecorder是 MediaStream Recording API 提供的用来进行媒体轻松录制的接口,他需要通过调用MediaRecorder()构造方法进行实例化。
if (navigator.mediaDevices.getDisplayMedia) {
let chunks = []
const constraints = {
audio: true
}
navigator.mediaDevices.getUserMedia(constraints).then(stream => {
const mediaRecorder = new MediaRecorder(stream)
mediaRecorderData.current = mediaRecorder
mediaRecorder.ondataavailable = (e) => {
chunks.push(e.data)
}
mediaRecorder.onstop = (e) => {
const blob = new Blob(chunks, { type: "audio/mp4; codecs=opus" })
chunks = []
const audioURL = window.URL.createObjectURL(blob)
player.current.src = audioURL
}
}, () => {
alert('授权失败!')
})
} else {
alert('浏览器不支持 getUserMedia')
}
这样,点击录音,在键盘⌨️上面按住 0123456,就会发出声音。