简体   繁体   English

React Native 与 Animated 同步声音

[英]React Native syncing sound with Animated

I'm making an app which has a metronome in it.我正在制作一个带有节拍器的应用程序。 I'm using react-native-sound and Animated.我正在使用 react-native-sound 和 Animated。 I need for the metronome sound to trigger with very high accuracy, and also be in sync with an animation.我需要节拍器声音以非常高的精度触发,并且与 animation 同步。 I'm not massively experienced, so I've used a hacky solution (triggering the samples with an Animated.listener), but it's extremely inefficient:我没有大量经验,所以我使用了一个 hacky 解决方案(使用 Animated.listener 触发样本),但效率极低:

  <Button
icon={this.state.paused ? <Icon name="play" size={25} color='white'/> : <Icon name="pause" size={25} color='white'/>}
onPress={() => {
  if (this.state.paused)
    {this.setState({paused: false});
    this.animateTiming();
    let loopCount = 0;
    this.animatedValue.addListener(({value}) => {
      loopCount++;
      if(value==1) loopCount=0;

      // metronome playback
      if ([0,60,120,180].includes(loopCount)) playSound(audioList[0], 0);
  });


    }

Does anyone have any suggestions of how to handle it better?有人对如何更好地处理它有任何建议吗? Thank you!谢谢!

Update #2更新#2

this.animateTiming() looks like this: this.animateTiming() 看起来像这样:

animateTiming(){
this.animatedValue.setValue(START_POINT);
Animated.loop(
    Animated.timing(this.animatedValue, {
      toValue: STOP_POINT,
      easing: Easing.linear,
      duration: 4000, //these are milliseconds
      useNativeDriver: true
    })
).start(); 

} }

The loop is 4000ms long, so at 60fps loopCount goes up to 240. Hence, [0,60,120,180] means "play the sound every second".循环长度为 4000 毫秒,因此在 60fps 时 loopCount 上升到 240。因此,[0,60,120,180] 表示“每秒播放声音”。 The delay happens at the beginning of each loop, when the render function is called.延迟发生在每个循环的开始,当调用渲染 function 时。 I've identified that the source of the delay (about 80ms) is rendering musical notation using VexFlow (see the example in "Getting Started" in this link ).我已经确定延迟的来源(大约 80 毫秒)是使用 VexFlow 渲染乐谱(请参阅此链接中“入门”中的示例)。

The question turns out to be, whether it's possible for the VexFlow rendering and the animation to run in parallel somehow (the audio needs to be perfectly in time, and a slight delay with rendering the notation is not a problem).问题是,VexFlow 渲染和 animation 是否有可能以某种方式并行运行(音频需要完全及时,渲染符号的轻微延迟不是问题)。 Pre-rendering notation is not feasible, as what is displayed depends on the user's actions in the previous loop cycle.预渲染符号是不可行的,因为显示的内容取决于用户在前一个循环周期中的操作。

[...] so at 60fps loopCount goes up to 240. Hence, [0,60,120,180] means "play the sound every second" [...] 所以在 60fps loopCount 上升到 240。因此,[0,60,120,180] 表示“每秒播放声音”

This is an assumption that it will be 60 fps.这是一个假设,它将是 60 fps。 Actual framerate will depend on capabilities of the device, and how much calculation is done each frame.实际帧率将取决于设备的功能,以及每帧进行多少计算。 It varies in time.它随时间变化。 Any fluctuation in FPS will result in sound being played at the wrong time. FPS 的任何波动都会导致声音在错误的时间播放。

I've identified that the source of the delay (about 80ms) is rendering musical notation [...]我已经确定延迟的来源(大约 80 毫秒)是渲染乐谱 [...]

It looks like you are experiencing a drop in fps.看起来您的 fps 有所下降。

Solution解决方案

Metronome should click in constant intervals, so the correct approach would be to calculate the time difference between frames and check if specified amount of time has passed;节拍器应该以恒定的间隔单击,因此正确的方法是计算帧之间的时间差并检查是否经过了指定的时间量; if so then play "click" sound.如果是这样,则播放“点击”声音。

These sources may come handy:这些来源可能会派上用场:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM