Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将音符写入wav文件_C#_Audio_Wav - Fatal编程技术网

C# 将音符写入wav文件

C# 将音符写入wav文件,c#,audio,wav,C#,Audio,Wav,我对如何记音符(如A、B、C#等)或和弦(同时记多个音符)并将其写入wav文件感兴趣 据我所知,每个音符都有一个与之相关的特定频率(完美音高)-例如A4(中间C上方的a)是440 Hz(完整列表向下2/3) 如果我的理解是正确的,这个音高是在频域中,因此需要对其应用快速傅里叶逆变换来生成时域等效物 我想知道的是: 和弦是如何工作的?他们是平均投球数吗 当wav文件的内容是波形时,如何指定播放每个音符的时间长度 多个音符被反向FFT转换成一个字节数组的结果如何,这些字节构成了wav文件中的数据

我对如何记音符(如A、B、C#等)或和弦(同时记多个音符)并将其写入wav文件感兴趣

据我所知,每个音符都有一个与之相关的特定频率(完美音高)-例如A4(中间C上方的a)是440 Hz(完整列表向下2/3)

如果我的理解是正确的,这个音高是在频域中,因此需要对其应用快速傅里叶逆变换来生成时域等效物

我想知道的是:

  • 和弦是如何工作的?他们是平均投球数吗
  • 当wav文件的内容是波形时,如何指定播放每个音符的时间长度
  • 多个音符被反向FFT转换成一个字节数组的结果如何,这些字节构成了wav文件中的数据
  • 与此相关的任何其他相关信息
谢谢你能给我的帮助。如果给出代码示例,我将使用C#,当前用于创建wav文件的代码如下所示:

int channels = 1;
int bitsPerSample = 8;
//WaveFile is custom class to create a wav file.
WaveFile file = new WaveFile(channels, bitsPerSample, 11025);

int seconds = 60;
int samples = 11025 * seconds; //Create x seconds of audio

// Sound Data Size = Number Of Channels * Bits Per Sample * Samples

byte[] data = new byte[channels * bitsPerSample/8 * samples];

//Creates a Constant Sound
for(int i = 0; i < data.Length; i++)
{
    data[i] = (byte)(256 * Math.Sin(i));
}
file.SetData(data, samples);
int通道=1;
int-bitsPerSample=8;
//WaveFile是创建wav文件的自定义类。
波形文件=新的波形文件(通道,比特采样,11025);
整数秒=60;
int samples=11025*秒//创建x秒的音频
//声音数据大小=通道数*每个采样位*采样
字节[]数据=新字节[通道*bitsPerSample/8*样本];
//发出持续的声音
for(int i=0;i

这会(不知何故)产生一种恒定的声音,但我不完全理解代码与结果之间的关系。

您的思路是正确的。:)

音频信号

您不需要进行逆FFT(可以,但需要为它找到一个库或实现它,并生成一个信号作为它的输入)。直接从IFFT生成我们期望的结果要容易得多,IFFT是具有给定频率的正弦信号

正弦的参数取决于要生成的音符和生成的波形文件的频率(通常等于44100Hz,在您的示例中使用的是11025Hz)

对于1Hz音调,您需要一个周期等于1秒的正弦信号。对于44100 Hz,每秒有44100个采样,这意味着我们需要一个周期等于44100个采样的正弦信号。由于正弦周期等于(2*Pi),我们得到:

对于440 Hz,我们得到:

sin(44100*f) = sin(440*tau)
44100*f = 440*tau
f = 440 * tau / 44100 = 440 * 2 * pi / 44100
在C#中,这可能是这样的:

double toneFreq = 440d;
double f = toneFreq * 2d * Math.PI / 44100d;
for (int i = 0; i<data.Length; i++)
    data[i] = (byte)(128 + 127*Math.Sin(f*i));
  data[i] = (data[i] + volume * Math.Sin(phaseshift + i * multiplier * 440.0))); 
     /\
    /  \__________
   /              \
  /                \
   A  D   S       R
double toneFreq=440d;
双f=toneFreq*2d*Math.PI/44100d;

对于(inti=0;i而言,您的思路是正确的

让我们看一下您的示例:

for(int i = 0; i < data.Length; i++)
  data[i] = (byte)(256 * Math.Sin(i));
如果相移为零,显然没有变化。2π的相移(或π的任意偶数倍)也没有变化,因为sin的周期为2π。0到2π之间的每个值都会在音调“开始”的位置沿波移动一点点

精确计算出正确的相移可能有点棘手。如果你读了我关于生成“连续下降”的文章Shepard幻觉音调,你会看到我用了一些简单的演算来确保一切都在没有任何pop的情况下持续变化。你可以使用类似的技术来找出正确的转变是什么,使pop消失

我正在尝试如何生成phaseshift值。“Arcin((新音符的第一个数据样本)-(上一个音符的最后一个数据样本))/noteVolume”是否正确

首先要意识到的是,可能没有一个“正确的值”。如果结束音非常响亮,并且在峰值结束,而开始音非常安静,那么新音调中可能没有与旧音调值匹配的点

假设有一个解,它是什么?你有一个结束样本,称它为y,你想找到相移x,这样

y = v * sin(x + i * freq)
当我为零时,这就是

x = arcsin(y / v)
然而,这可能不太正确!假设你有

你想附加

有两种可能的相移

大胆猜测哪一个听起来更好。:-)

弄清楚你是处于波浪的“上冲”还是“下冲”可能有点棘手。如果你不想算出真正的数学,你可以做一些简单的试探,比如“连续数据点之间的差异符号在转换时改变了吗?”

技术2:ADSR信封

如果你正在模拟一些听起来像真实乐器的东西,那么你可以通过如下改变音量来获得好的效果

你要做的是每个音符有四个不同的部分,叫做攻击、衰减、维持和释放。乐器上演奏的音符的音量可以这样建模:

double toneFreq = 440d;
double f = toneFreq * 2d * Math.PI / 44100d;
for (int i = 0; i<data.Length; i++)
    data[i] = (byte)(128 + 127*Math.Sin(f*i));
  data[i] = (data[i] + volume * Math.Sin(phaseshift + i * multiplier * 440.0))); 
     /\
    /  \__________
   /              \
  /                \
   A  D   S       R
音量从零开始。然后,攻击发生了:声音迅速上升到峰值音量。然后,它会稍微衰减到维持的水平。然后它保持在这个水平,也许在音符播放时缓慢下降,然后释放回零

如果你这样做,那么就没有流行音乐,因为每个音符的开始和结束都是零音量的。发行版确保了这一点

不同的仪器有不同的“信封”。例如,管风琴的攻击、腐烂和释放时间都非常短;一切都是持续的,而持续是无限的。您现有的代码就像一个管风琴。与钢琴相比。同样,短暂的攻击,短暂的衰减,短暂的释放,但声音在持续的过程中会逐渐变得安静


攻击、衰减和释放部分可能很短,太短而听不见,但足够长以防止弹出。尝试在音符播放时改变音量,看看会发生什么。

还没有人提到
  data[i] = (data[i] + volume * Math.Sin(phaseshift + i * multiplier * 440.0))); 
y = v * sin(x + i * freq)
x = arcsin(y / v)
     /\
    /  \__________
   /              \
  /                \
   A  D   S       R
DECAY = 0.99
while( n < 99999 )
    outbuf[n++] = buf[k]

    newVal = DECAY  *  ( buf[k] + buf_prev ) / 2

    buf_prev = buf[k]
    buf[k] = newVal

    k = (k+1) % 100