Use-sound Package: Sound Effects in React Applications

Maybe the fact is that I was professionally engaged in sound, but I want the web to be louder.

I know that many will not support me in this desire. And not without reason! Historically, sounds on the Internet were used extremely unsuccessfully and ugly:

  • In the early days of the web, some pages played background MIDI music.
  • Pop-up scammers use sounds to achieve their bad goals. They, with the help of sounds, seek to attract the attention of users and make fraud more believable.
  • The sound is present in automatically starting videos (well, this is absolutely a nightmare).

True, I am sure that completely abandoning the sound is as if a child is splashed out with water. Sounds can emphasize user actions; they can enhance feedback. The sound can brighten up a little boring actions. If the sounds on the web pages are used with taste, they can improve the user's experience of the project, making it more “tangible” and real. This idea is not new: in games and in mobile applications sounds are constantly used. In fact, the web is a strange exception to the general trend. Most digital products that come to my mind use sounds. I'm not talking about the tactile response that is used in mobile applications to bring them closer to reality.





In the course of working on my blog, I wanted to experiment with sound. Many of the interface elements of my blog that users interact with produce quiet short sounds. For example, in the upper right part of the blog’s home page, there are a couple of buttons to switch themes and to turn sound on and off.

Since sounds on the web are rarely used, their use can have a great impact on the perception of the site by users. This is a kind of secret weapon of the developer, the use of which can lead to a surprisingly large positive impact on certain projects.

In order to simplify the use of sounds, I designed the hook used by me to work with sounds in the form of an independent npm package use-sound and published it. Here I will talk about the capabilities of this hook and share tips on using sound on the web.

If you are eager to see the code and start using this hook - here is its GitHub repository.

Overview


The package use-soundis a React hook that helps developers use sound effects. Here is an example:

import useSound from 'use-sound';
import boopSfx from '../../sounds/boop.mp3';
const BoopButton = () => {
  const [play] = useSound(boopSfx);
  return <button onClick={play}>Boop!</button>;
};

Using this hook adds approximately 1 Kb to the project build. True, he, in asynchronous mode, loads a third-party Howler dependency , the size of which is 10 KB.

The hook gives the developer many nice features. Among them, I want to note the following:

  • Prematurely stop playback, as well as pause and resume playback.
  • Downloading something like a sound “sprite sheet” and dividing it into separate sounds.
  • Setting the playback speed with the ability to speed up and slow down the playback of sounds.
  • Lots of event listeners.
  • Many advanced features available thanks to Howler.

Here is the hook documentation where you can find a detailed guide to its use and API reference.

Use-sound basics


â–ŤInstallation


First you need to install the package using yarn or npm:

#  yarn
yarn add use-sound
#  NPM
npm install use-sound

â–Ť Import


The package use-soundexports the only default value - this is a hook useSound. You can import it like this:

import useSound from 'use-sound';

In addition, you will need to import the audio files that you plan to use.

If, when working on React projects, you use something like create-react-appGatsby, then you should be able to import MP3 files in the same way as you import other resources - like images:

import boopSfx from '../../sounds/boop.mp3';

If you use a self-written Webpack configuration, then you will need to use the file-loader loader to process .mp3 files .

In addition, you can work with sound files placed in folders publicor static. For example, the demos shown in this article use static files located in a public folder.

Search and prepare sounds


Installing dependencies and writing code is only half the battle. For scoring pages, we need to select the appropriate sounds.

My favorite resource to look for sounds on is freesound.org . Almost all the sounds used in my blog, I found there. There are many sounds licensed under Creative Commons Zero . To download files you need to register on the resource. You can use sounds for free.

Be prepared for the fact that in order to select the right sound you have to seriously rummage through the contents of freesound.org. The point here is, for example, that many sounds are of poor quality. The process of finding the right sound can be compared to the process of searching for a needle in a haystack. And the preparation of the sound found for actual use resembles a facet of uncut diamond.

â–ŤPreparation of sounds


Many sounds taken from freesound.org need some improvements:

  • Sounds, like strings, can be framed by empty space. Silence fragments are usually cut out, as a result, the corresponding sound effect is reproduced immediately after the occurrence of the voiced event.
  • When preparing sounds, you may need to adjust their volume, making it so that all sounds used in one project have the same volume.
  • Freesound.org has sounds stored in various audio formats. You may very well need to convert the sounds you like to MP3.

You can use Audacity to complete all of these edits. This is a free open source cross-platform audio editor. Here I will not talk about how to use this editor, but there are many great tutorials on it.

Why am I talking about converting sounds to MP3? The fact is that before there was no audio format supported by all browsers. Therefore, it was commonplace to include MP3, AIFF, and WAV files in projects and use them in environments that support them.

In modern conditions, fortunately for us, the MP3 format is supported by all major browsers, including IE 9. The sound stored in the MP3 format is also very well compressed. And this allows you to go to files much smaller than using alternative formats that encode sound without loss of quality.

Sound and Availability


Although I advocate the use of sounds on the web, I admit that not all users will like it. And here we are talking about considerations that go beyond the subjective desire for silence.

People who have vision problems use screen readers to use webpages. Moreover, we are talking not only about those who do not see the pages. Screen readers, for example, are used by people with dyslexia who find it difficult to perceive text, and people with other similar problems. Screen readers are programs that parse documents and read texts. If a site contains a lot of sound effects, they can interfere with the normal operation of programs that read text from the screen. And this, in turn, will prevent people who rely on such programs from working with the site.

For this reason, it is important that a button to turn sound on and off be included in the pages of the site. Moreover, such a button should be available for keyboard navigation (using the Tab key). Ideally, until the user reaches such a button using the Tab key, no sounds should be played. In addition, it is necessary that the web project would remember the state of this button - so the user does not have to constantly resort to it to mute the sound.

On the other hand, hearing impaired users will not even know that certain interactions with pages are accompanied by sound. The same applies to people who work on the Internet with the sound turned off. For this reason, it is important not to rely solely on sound when performing certain important actions. If the sound is used as a confirmation of some user action, make sure that a visual confirmation of this action is also displayed on the page. Sites should remain fully functional and sound free.

Recipes


Take a look at a few examples (in the corresponding section of the original of this article, you can experiment with them interactively and listen to the sounds made by different controls).

â–Ť Check box


I really like this flag. If you use a mouse, first click on it very quickly, and then so that there is a slight pause between the moment you click and release the mouse button.

function Demo() {
  const [isChecked, setIsChecked] = React.useState(
    false
  );

  const [playActive] = useSound(
    '/sounds/pop-down.mp3',
    { volume: 0.25 }
  );
  const [playOn] = useSound(
    '/sounds/pop-up-on.mp3',
    { volume: 0.25 }
  );
  const [playOff] = useSound(
    '/sounds/pop-up-off.mp3',
    { volume: 0.25 }
  );

  return (
    <Checkbox
      name="demo-checkbox"
      checked={isChecked}
      size={24}
      label="I agree to self-isolate"
      onChange={() => setIsChecked(!isChecked)}
      onMouseDown={playActive}
      onMouseUp={() => {
        isChecked ? playOff() : playOn();
      }}
    />
  );
}

â–Ť Early interruption of sound reproduction


Sometimes you want the sound to play only when the user interacts with a certain control. Pay attention to the way in the following example that the sound is reproduced only when the pointer is above the control.

function Demo() {
  // ,  ,  'rising-pops' :
  // - fanfare
  // - dun-dun-dun
  // - guitar-loop
  const soundUrl = '/sounds/rising-pops.mp3';

  const [play, { stop }] = useSound(
    soundUrl,
    { volume: 0.5 }
  );

  const [isHovering, setIsHovering] = React.useState(
    false
  );

  return (
    <Button
      onMouseEnter={() => {
        setIsHovering(true);
        play();
      }}
      onMouseLeave={() => {
        setIsHovering(false);
        stop();
      }}
    >
      <ButtonContents isHovering={isHovering}>
        Hover over me!
      </ButtonContents>
    </Button>
  );
}

â–ŤIncreasing pitch


And here is an example of one interesting effect. It consists in the fact that the sound reproduced by the next click on the Like button is higher than the sound reproduced by the previous click on it:

function Demo() {
  const soundUrl = '/sounds/glug-a.mp3';

  const [playbackRate, setPlaybackRate] = React.useState(0.75);

  const [play] = useSound(soundUrl, {
    playbackRate,
    volume: 0.5,
  });

  const handleClick = () => {
    setPlaybackRate(playbackRate + 0.1);
    play();
  };

  return (
    <Button onClick={handleClick}>
      <span role="img" aria-label="Heart">
      </span>
    </Button>
  );
}

â–Ť Button to start and pause playback


Here is the implementation code for the button to start and pause the sound, which will help you in developing the new Spotify:

function Demo() {
  const soundUrl = '/sounds/guitar-loop.mp3';

  const [play, { stop, isPlaying }] = useSound(soundUrl);

  return (
    <PlayButton
      active={isPlaying}
      size={60}
      iconColor="var(--color-background)"
      idleBackgroundColor="var(--color-text)"
      activeBackgroundColor="var(--color-primary)"
      play={play}
      stop={stop}
    />
  );
}

▍Sound “sprite lists”


If you plan to use a lot of sounds in your React-component, then it may make sense to use sound “sprite lists”. Sound sprite list is a file that contains many different sounds. By packing them into a single file, we increase the convenience of working with them and avoid making many parallel HTTP requests to download individual files (I hope that someday we will be able to use HTTP / 2 multiplexing).

Here we use the sound "sprite list" to create a drum machine. You can play virtual reels either with the mouse or with the keys 1-4 on the keyboard.

function Demo() {
  const soundUrl = '/sounds/909-drums.mp3';

  const [play] = useSound(soundUrl, {
    sprite: {
      kick: [0, 350],
      hihat: [374, 160],
      snare: [666, 290],
      cowbell: [968, 200],
    }
  });

  //  ,   'keydown',
  //    .
  useKeyboardBindings({
    1: () => play({ id: 'kick' }),
    2: () => play({ id: 'hihat' }),
    3: () => play({ id: 'snare' }),
    4: () => play({ id: 'cowbell' }),
  })

  return (
    <>
      <Button
        aria-label="kick"
        onMouseDown={() => play({ id: 'kick' })}
      >
        1
      </Button>
      <Button
        aria-label="hihat"
        onMouseDown={() => play({ id: 'hihat' })}
      >
        2
      </Button>
      <Button
        aria-label="snare"
        onMouseDown={() => play({ id: 'snare' })}
      >
        3
      </Button>
      <Button
        aria-label="cowbell"
        onMouseDown={() => play({ id: 'cowbell' })}
      >
        4
      </Button>
    </>
  );
}

Details on the use of sound "sprite lists" in the package use-soundcan be found here .

Summary


In the area of ​​the use of sounds when developing websites, I am most concerned about the fact that this is an area that has been studied very little. I’ve been experimenting with sounds for quite some time, but I still feel that I’m only at the very beginning of the journey.

So, now you have tools at your disposal that you can use to start your own experiments with sound. I suggest you do this and find out where it will lead you.

Dear readers! How do you feel about using sounds on web pages?


All Articles