使用GO从头开始音频:提取断点

2020-08-09 12:17:38

到目前为止,我们对断点所做的一切都涉及到创建一个断点文件,并使用此文件自动执行部分曲目。现在我们来看看如何利用现有的轨迹并从中提取一些断点。对于这篇文章,我们将看看如何从.wave文件中提取振幅,因为这是我们可以提取的最简单的属性之一。

这里没有什么是我们在之前的测试中没有看到的,相反,我们将结合我们已经学到的知识来创建一个新的工具来实现这一点。

从本质上讲,这很简单,但我们将对此算法进行两个小的修改。首先,我们不想只为每个帧生成一个断点,这只会产生一个与我们的帧数据相等的列表。我们只需要按一定的时间间隔(例如每10ms)拍摄一次快照,就可以使用更少的空间,并且可以利用在特定时间查找断点的值时发生的线性插值。

对当前断点代码的一个小扩展是,我们需要能够将样本“批处理”成给定时间的切片。

BatchSamples函数将接受64位的Wave和Second作为输入,因为这为我们提供了足够的数据来批处理帧。给定特定的SampleRate,我们知道每秒在文件中搜索的样本数。有了这些信息,我们就可以找到每秒的帧数。虽然每秒的帧数仅等于单声道文件的每秒采样数,但适应多声道音频只需将SampleSize乘以声道数即可。

因此,SampleSize可以表示为:SampleSize=SampleRate*Channels*Second。

当我们知道样本大小时,我们可以将原始帧分割成这种大小的切片。

Func BatchSamples(Data Wave,Second Float64)[][]Frame{IF Second==0{Return[][]Frame{Data.。帧,}}个样本:=数据。Frames sampleSize:=int(float64(data.。SampleRate*数据。NumChannels)*float64(秒))Batches:=len(Samples)/sampleSize if len(Samples)%sampleSize!=0{Batches++}Batted:=make([][]Frame,Batches)//应向上舍入...。对于i:=0;i<;len(批处理);i++{start:=i*sampleSize if start>;len(Samples){Return Batched}maxTake:=i*sampleSize+sampleSize if maxTake>;=len(Samples)-1{maxTake=len(Samples)}subs:=Samples[start:maxTake]Batked[i]=subs}Return Batted}

一旦我们可以将帧分割成批次,我们就可以调用BatchSamples(wave,x)来获取给定持续时间的请求批次。然后,我们可以找到所有这些的最大振幅,并跟踪所有批次的最大振幅。

设置代码与通常相同,我们使用GoAudio解析输入文件。不过,现在我们还将把帧发送到“BatchSamples”函数。(为简洁起见,忽略错误处理)。

Func main(){标志。Parse()infile:=*输入输出文件:=*输出波形,_:=wav。ReadWaveFile(Infile)帧持续时间:=15.0ms//15ms刻度:=帧持续时间/1000.0批:=wav。BatchSamples(波形、刻度)...。

做完这件事后,我们将把样品分批放在15毫秒的切片中。我们将继续对它们进行迭代,并收集在每个元素中找到的最大振幅。因为我们最终需要将其写入输出文件,所以现在我们将其存储在StringBuilder中。

我们必须跟踪的另一件事是哪个时间将被插入到时间中:断点文件的值对。对于每个批次,该时间值将是15ms的增量。

..。Strout:=字符串。生成器{}已用时间:=0.0 for_,b:=范围批次{maxa:=maxAmp(B)es:=strconv。格式浮动(已过,#39;f#39;,8,64)fs:=strconv.。格式浮动(Maxa,#39;f';,8,64)Strout(Maxa,#39;f';,8,64)Strout.。WriteString(es+";:";+fs+";\n";)已超过+=ticks}ioutil。WriteFile(输出文件,[]字节(Strout.。String()),0644)}。

最后,剩下的就是通过迭代切片中的每一帧并返回最大放大器来填充maxAmp函数。

函数max Amp(ss[]WAV.。Frame)float64{if len(Ss)==0{return 0}max:=-1.0//因为它们在-1范围内。1 for_,a:=range ss{if float64(A)>;max{max=float64(A)}}返回float64(Max)}

当我们运行此程序时,请运行main.go-i input.wav-w 15-o output.brk,我们可以生成abreakpoint文件。我已经创建了一个振幅可变的样本波形(我将在以后的博客中写到这一点)。你可以在这里收听。

使用Audacity和您最喜欢的绘图工具,您可以将波形与断点提取器生成的波形进行比较。

如果你喜欢这篇文章,并想知道我什么时候写了新帖子,最好的更新方式就是在Twitter上关注我。