如何防止两个声音同时播放?

huangapple go评论143阅读模式
英文:

How can I prevent two sounds from playing simultaneously?

问题

在我的应用中,我有两个可按的地方,如果你按其中一个,它会播放相应的声音。当然,如果你按另一个,它也会播放相应的声音。

但是我想要这样的效果:当一个声音正在播放时,如果我按另一个,先前的声音将停止播放,而不是同时播放两个声音,我该怎么做?

这是我的代码。
这两个是可按的:

<SoundPlayer voice={route.params.voice}>
  <English English={route.params.English} />
</SoundPlayer>

<SoundPlayer voice={route.params.voice2}>
  <NoteDesc noteDesc={route.params.noteDesc} />
</SoundPlayer>

这是用于播放声音的部分:

import React, { useEffect, useState } from "react";
import {
  Button,
  Text,
  TouchableWithoutFeedback,
  TouchableOpacity,
  StyleSheet,
  View,
} from "react-native";
import { Audio } from "expo-av";

export default function SoundPlayer({ voice, children }) {
  const [sound, setSound] = useState();

  async function playSound() {
    console.log("Loading Sound");
    if (sound) {
      console.log("Unloading Sound");
      await sound.unloadAsync();
    }
    const { sound: newSound } = await Audio.Sound.createAsync(voice);
    setSound(newSound);

    console.log("Playing Sound");
    await newSound.playAsync();
  }

  useEffect(() => {
    return sound
      ? () => {
          console.log("Unloading Sound");
          sound.unloadAsync();
        }
      : undefined;
  }, [sound]);

  return (
    <View>
      <TouchableOpacity onPress={playSound}>{children}</TouchableOpacity>
    </View>
  );
}
const styles = StyleSheet.create({
  container: {},
  English: {
    color: "snow",
    fontSize: 30,
    textAlign: "center",
  },
});

提前感谢你。

英文:

In my app, I have two pressable places, and if you press one of them, it plays the corresponding sound.
And, if you press the other one, of course, it plays the corresponding sound.

But I want something like this: when one is being played, if I press the other one, the previous one will be stopped playing, rather than playing two of them at the same time, how can I do that?

Here is my code.
These two are pressable:

&lt;SoundPlayer voice={route.params.voice}&gt;
  &lt;English English={route.params.English} /&gt;
&lt;/SoundPlayer&gt;

&lt;SoundPlayer voice={route.params.voice2}&gt;
  &lt;NoteDesc noteDesc={route.params.noteDesc} /&gt;
&lt;/SoundPlayer&gt;

This is for playing sounds:

import React, { useEffect, useState } from &quot;react&quot;;
import {
  Button,
  Text,
  TouchableWithoutFeedback,
  TouchableOpacity,
  StyleSheet,
  View,
} from &quot;react-native&quot;;
import { Audio } from &quot;expo-av&quot;;

export default function SoundPlayer({ voice, children }) {
  const [sound, setSound] = useState();

  async function playSound() {
    console.log(&quot;Loading Sound&quot;);
    if (sound) {
      console.log(&quot;Unloading Sound&quot;);
      await sound.unloadAsync();
    }
    const { sound: newSound } = await Audio.Sound.createAsync(voice);
    setSound(newSound);

    console.log(&quot;Playing Sound&quot;);
    await newSound.playAsync();
  }

  useEffect(() =&gt; {
    return sound
      ? () =&gt; {
          console.log(&quot;Unloading Sound&quot;);
          sound.unloadAsync();
        }
      : undefined;
  }, [sound]);

  return (
    &lt;View&gt;
      &lt;TouchableOpacity onPress={playSound}&gt;{children}&lt;/TouchableOpacity&gt;
    &lt;/View&gt;
  );
}
const styles = StyleSheet.create({
  container: {},
  English: {
    color: &quot;snow&quot;,
    fontSize: 30,
    textAlign: &quot;center&quot;,
  },
});

Thank you in advance.

答案1

得分: 1

You have this sound state in SoundPlayer. It will be unique to each <SoundPlayer /> call. So at this point, whenever playSound is called, sound refers only to the current component's playing sound.

I would suggest you move this const [sound, setSound] = useState() in an outer parent component, for example with the Context API. Something like this:

// SoundContextProvider.js

import { useState, createContext, useContext } from "react";

const SoundContext = createContext();

export default function SoundContextProvider({ children }) {
  const [sound, setSound] = useState();
  return <SoundContext.Provider value={{ sound, setSound }}>{children}</SoundContext.Provider>;
}

export function useSoundContext() {
  return useContext(SoundContext);
}

Grab it inside SoundPlayer like below. This way you are always referring to the same sound instance:

import { useSoundContext } from "./SoundContextProvider"; // Make sure you use the correct path.

export default function SoundPlayer({ voice, children }) {
  const { sound, setSound } = useSoundContext();

  // ...
}

Finally, ensure, for example, in App.js, you render your components wrapped by SoundContextProvider:

import SoundContextProvider from "./SoundContextProvider"; // Make sure you use the correct path.
export default function App() {
  // ...
  return <SoundContextProvider>{/* Your components go here*/}</SoundContextProvider>;
}
英文:

You have this sound state in SoundPlayer. It will be unique to each &lt;SoundPlayer /&gt; call. So at this point, whenever playSound is called, sound refers only to the current component's playing sound.

I would suggest you move this const [sound, setSound] = useState() in an outer parent component, for example with the Context API. Something like this:

// SoundContextProvider.js

import { useState, createContext, useContext } from &quot;react&quot;;

const SoundContext = createContext();

export default function SoundContextProvider({ children }) {
  const [sound, setSound] = useState();
  return &lt;SoundContext.Provider value={{ sound, setSound }}&gt;{children}&lt;/SoundContext.Provider&gt;;
}

export function useSoundContext() {
  return useContext(SoundContext);
}

Grab it inside SoundPlayer like below. This way you are always referring to the same sound instance:

import { useSoundContext } from &quot;./SoundContextProvider&quot;; // Make sure you use the correct path.

export default function SoundPlayer({ voice, children }) {
  const { sound, setSound } = useSoundContext();

  // ...
}

Finally, ensure, for example, in App.js, you render your components wrapped by SoundContextProvider:

import SoundContextProvider from &quot;./SoundContextProvider&quot;; // Make sure you use the correct path.
export default function App() {
  // ...
  return &lt;SoundContextProvider&gt;{/* Your components goe here*/}&lt;/SoundContextProvider&gt;;
}

huangapple
  • 本文由 发表于 2023年5月7日 15:19:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76192639.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定