- Prepare audio files
- HTML5 audio element
- Data model extension
- getAudioFileName
- Testing
- Dynamic audio playing
Prepare audio files
We will use a short mp3 files for each key value. In the folder keyboardData
create folders: en
, ru
, ar
. Move audio files with numbers (for 3 langs) to the folders.
GITHUB
Note:
If you need to make many files from one, I highly recommend free audio editor Audacity
. There you can select parts of an audio and attach text labels to them (ctrl+b
). Then in menu: File
--> Export
--> Export Multiple
--> Split based on: Label
.
For example, you have 1 audio file with numbers from 0 to 9.
You will get files: 0.mp3
, 1.mp3
, ... 9.mp3
.
HTML5 audio element
In App.js
methods, at the beginning of setActiveKey
add 2 lines:
App.js methods
setActiveKey(keyContent) {
const audio = new Audio(`./keyboardData/en/1.mp3`);
audio.play();
...
}
That's how audio element works.
Now when you click on any button, will be played one file en/1.mp3
. You guess that we need to play different files. But there is a problem to identify them in our data model. If you remember, each key is represented by object:
const key = {
code,
label,
main,
shifted
}
Data model extension
Key data aren't filled in the same way. Keys have such different set of props:
file naming
- Only
code
{
code: 'F1'
}
File name F1.mp3
is good for such keys.
-
main
andshifted
{
code: 'Digit1',
main: '1',
shifted: '!',
// should add:
shiftedName: 'exclamation mark'
},
Here we cannot use code
as before. Because there is only 1 code
, but we need 2 audio files for main
and shifted
values.
Furthermore, !
is forbidden symbol for file names. So it would be good to have an additional field shiftedName: 'exclamation mark'
, that we'll use in a file name.
Value of main
is good for filename 1.mp3
, but sometimes we will need an additional field mainName
.
1.mp3
or exclamation mark.mp3
would be good filenames for keyContent
above.
- lower and upper case letters
{
code: 'KeyQ',
main: 'q',
shifted: 'Q',
// add:
shiftedName: 'q'
},
Here it is enough to have only 1 file q.mp3
for both values q
and Q
.
How do we fill our data now? We add to every main
and shifted
values that we can't or don't want to use as a file name, additional values: mainName
and/or shiftedName
.
The idea behind this different approach to each key type, instead of writing filename for every key value, is that we are trying to avoid overloading of our keyboardData/lang.js
files. So we will add a minimum info do keyboard data file, and then calculate filenames from that minimum.
getAudioFileName
const getAudioFileName = (keyContent, shiftKey) => {
const { main, mainName, shifted, shiftedName, code } = keyContent
let fileName
if (shiftKey) {
// will be returned 1 of 3 values (if it exist). priority to the first one
fileName = shiftedName || shifted || code
} else {
fileName = mainName || main || code
}
// to have a guarantee, that everything is written in the same (lower) case
return fileName.toLowerCase()
}
Notice, that we call any audio file by its lower case name. So we don't need to change keyboard data for values like q-Q
. When you name files make sure they are in lowercase.
Testing
When you wrote a function, and you're not sure if it works or not, you should test it.
The simplest way: copy/paste the function to console (Chrome --> DevTools --> Console
). (code above without word const
)
Also copy to the console keyContent
examples that we wrote before. Put them to the array input
:
const input = [
{ code: 'F1' },
{
code: 'Digit1',
main: '1',
shifted: '!',
shiftedName: 'exclamation mark'
},
{
code: 'KeyH',
main: 'h',
shifted: 'H'
}
]
Then call getAudioFileName
with these data entities and different shiftKey
values, in the console.
getAudioFileName(input[0], false) // f1
getAudioFileName(input[0], true) // f1
getAudioFileName(input[1], false) // 1
getAudioFileName(input[1], true) // exclamation mark
getAudioFileName(input[2], false) // h
getAudioFileName(input[2], true) // h
That is called testing
. Programmers save such a code with:
-
input
, -
call(input)
, correct output
to special files -- called tests
. Then, after codebase has changed, we run the tests
to check that we haven't broken anything.
Dynamic audio playing
Add that function definition at the top of Keyboard.js
, just after imports:
Keyboard.js
import Keyboard from './components/Keyboard.js'
import LangSwitcher from './components/LangSwitcher.js'
const getAudioFileName = (keyContent, shiftKey) => {
...
}
And call it where we played static audio before.
Keyboard.js methods
setActiveKey(keyContent) {
const fileName = getAudioFileName(keyContent, this.shiftKey)
const audio = new Audio(
`./keyboardData/${this.currentLang}/${fileName}.mp3`
)
audio.play()
...
}
Now when you click on different buttons, you hear a particular key sound, even when you switch languages. Don't forget, that for now we have files only for numbers 0, 1, ..., 9
-- they are correct for en
and ru
. But for playing Arabic numbers you should add their mainName
s to keyboardData/ar.js
.
keyboardData/ar.js
{
code: 'Digit1',
main: 'Ω‘',
// add:
mainName: '1',
shifted: '!'
},
...
Or you should rename files to Ω‘.mp3
, Ω’.mp3
e.t.c.
As you can see, our approach of file naming and data filling is flexible.
Top comments (0)