首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何实现颗粒合成(沥青移位器)?

如何实现颗粒合成(沥青移位器)?
EN

Stack Overflow用户
提问于 2022-02-24 09:26:56
回答 1查看 249关注 0票数 0

因为音乐速度和音高是耦合在一起的,如果我加速音乐,音高也会增加。相反,如果我放慢音乐的速度,音高也会下降。

然而,I saw that using granular synthesis, I can decouple speed and pitch.因此,我目前正在努力实现粒度合成。

首先,我认为我成功地实现了双速和半速,而球场是一样的。代码与以下代码相同:

※晶粒尺寸为2 0 0 0。这意味着我用0.04ms的声音作为一颗谷物。(2000年样本*1s/ 44100样本= 0.04s =40毫秒)

代码语言:javascript
运行
复制
// get music
const $fileInput = document.createElement('input');
$fileInput.setAttribute('type', 'file');
document.body.appendChild($fileInput);

$fileInput.addEventListener('change', async (e) => {
  const music = await $fileInput.files[0].arrayBuffer();
  const actx = new (window.AudioContext || window.webkitAudioContext)({ latencyHint: 'playback', sampleRate: 44100 });
  const audioData = await actx.decodeAudioData(music);
  const original = audioData.getChannelData(0);
  const arr = [];
  const grainSize = 2000;

  // Please choose one code out of double speed code or half speed code
  // copy and paste audio processing code here
});
代码语言:javascript
运行
复制
// double speed
// ex: [0,1,2,3, 4,5,6,7, 8] => [0,1, 4,5, 8] discard 2 items out of 4 items
for (let i = 0; i < original.length; i += grainSize) {
  if (original[i + (grainSize / 2) - 1] !== undefined) {
    for (let j = 0; j < grainSize / 2; j++) {
      arr.push(original[i + j]);
    }
  } else {
    for (let j = i; j < original.length; j++) {
      arr.push(j);
    }
  }
}
代码语言:javascript
运行
复制
// half speed
// ex: [0,1, 2,3, 4] => [0,1,0,0, 2,3,0,0, 4,0,0] add 'two' zeros after every 'two' items
for (let i = 0; i < original.length; i += grainSize) {
  if (original[i + grainSize - 1] !== undefined) {
    for (let j = 0; j < grainSize; j++) {
      arr.push(original[i + j]);
    }
  } else {
    for (let j = i; j < original.length; j++) {
      arr.push(original[j]);
    }
  }

  for (let j = 0; j < grainSize; j++) {
    arr.push(0);
  }
}
代码语言:javascript
运行
复制
// play sound
const f32Arr = Float32Array.from(arr);
const audioBuffer = new AudioBuffer({ length: arr.length, numberOfChannels: 1, sampleRate: actx.sampleRate });
  
audioBuffer.copyToChannel(f32Arr, 0);

const absn = new AudioBufferSourceNode(actx, { buffer: audioBuffer });
  
absn.connect(actx.destination);
absn.start();

但是问题是,我完全不知道如何实现螺距移位器(即不同的螺距,相同的速度)。

就我看来,同样的速度意味着相同的AudioBuffer大小。因此,我手中唯一的变量是晶粒大小。但我真的不知道该怎么办。如果你能分享你的一些知识,我们将不胜感激。非常感谢!

致菲尔·弗里霍夫纳

你好,谢谢你的善意解释。我试过你的方法。据我所知,您的方法是一个执行以下操作的过程:

代码语言:javascript
运行
复制
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // input data (10 samples)
→ [0, 2, 4, 6, 8] // double speed, 1 octave high (sampling interval: 2)
→ [0, 0, 2, 2, 4, 4, 6, 6, 8, 8] // change duration

结果是1倍频程高,同样的持续时间(成功的音高移动)。但是,如果我从采样间隔为1.5的输入数据进行采样,我不知道该怎么办?我的意思是,我不知道如何使[0, 1, 3, 4, 6, 7, 9]的长度与输入数据的长度相同。

代码语言:javascript
运行
复制
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] // input data
// from
[0, 1, 3, 4, 6, 7, 9] // sampling interval: 1.5
// to
[?, ?, ?, ?, ?, ?, ?, ?, ?, ?]

同时,我了解到音高转换可以通过一种方式来实现,据我所知,方法如下:

  • 1使每个颗粒以与原源
  • 2相同的位置启动,以不同的速度播放每个颗粒。

此外,我发现,如果我转换如下输入数据,我可以实现音高移位和时间拉伸:

代码语言:javascript
运行
复制
input data = [0, 1, 2, 3, 4, 5, 6, 7]
grain size = 4

<pitch shifting>

in case of p = 2
result = [0, 2, 0, 2, 4, 6, 4, 6] // sounds like one octave high
// If I remember correctly, [0, 2, 0, 0, 4, 6, 0, 0] is also fine
// (and it is more fit to the definition above ([1] and [2])
// but the sound was not good (stuttering).
// I found that [0, 2, 0, 2...] is better.

in case of p = 1.5
result = [0, 1, 3, 0, 4, 5, 7, 4]

in case of p = 0.5
result = [0, 0, 1, 1, 4, 4, 5, 5] // sounds like one octave low

<time stretching>

in case of speed = 2
result = [0, 1, 4, 5]

in case of speed = 1.2
result = [0, 1, 2, 4, 5, 6]

in case of speed = 0.5
result = [0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7]
// If I remember correctly, [0, 1, 2, 3, 0, 0, 0, 0...] is also fine
// but the sound was not good (stuttering)

in case of speed = 0.75
result = [0, 1, 2, 3, 0, 4, 5, 6, 7, 4]

不管怎样,谢谢你的回答。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71249756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档