【问题标题】:creating audio file based on frequencies根据频率创建音频文件
【发布时间】:2020-08-02 18:35:51
【问题描述】:

我正在将 node.js 用于我正在做的项目。 该项目是将单词转换为数字,然后获取这些数字并创建音频输出。 音频输出应将数字播放为频率。例如,我有一个数字数组 [913, 250,352] 现在我想将这些数字作为频率播放。 我知道我可以使用音频 API 或任何其他允许我这样做的第三方包在浏览器中播放它们。 问题是我想创建一些音频文件,我尝试将这些数字转换为音符,然后将其保存为 Midi 文件,我成功了,但问题是 midi 文件采用频率,将它们转换为最接近的音符(例如: 913 将转换为 932.33HZ - 即音符编号 81),

    // add a track
    var array = gematriaArray
    var count = 0
    var track = midi.addTrack()
    var note
    
    for (var i = 0; i < array.length; i++) {
            note = array[i]

        track = track.addNote({

            //here im converting the freq -> midi note.
            midi: ftom(parseInt(note)),
            time: count,
            duration: 3
        })
        count++
    }

    // write the output
    fs.writeFileSync('./public/sounds/' + name + random + '.mid', new Buffer.from(midi.toArray()))

我搜索了互联网,但找不到任何可以提供帮助的信息。 我真的很想有一个文件,用户可以下载这些数字作为频率,有人知道可以做些什么来得到这个结果吗?

提前感谢帮助者。

【问题讨论】:

    标签: node.js audio frequency midi


    【解决方案1】:

    此函数将使用浮点值填充缓冲区,这些浮点值表示给定频率的原始音频曲线的高度

    var pop_audio_buffer_custom = function (number_of_samples, given_freq, samples_per_second) {
    
        var number_of_samples = Math.round(number_of_samples);
    
        var audio_obj = {};
        
        var source_buffer = new Float32Array(number_of_samples);
    
        audio_obj.buffer = source_buffer;
    
        var incr_theta = (2.0 * Math.PI * given_freq) / samples_per_second;
        var theta = 0.0;
    
        for (var curr_sample = 0; curr_sample < number_of_samples; curr_sample++) {
    
            audio_obj.buffer[curr_sample] = Math.sin(theta);
    
            console.log(audio_obj.buffer[curr_sample] , "theta ", theta);
    
            theta += incr_theta;
        }
        
        return audio_obj;
    
    };       //      pop_audio_buffer_custom
    
    var number_of_samples = 10000; // long enough to be audible
    var given_freq = 300;
    var samples_per_second = 44100;  // CD quality sample rate
    var wav_output_filename = "/tmp/wav_output_filename.wav"
    
    var synthesized_obj = {};
    
    synthesized_obj.buffer = pop_audio_buffer_custom(number_of_samples, given_freq, samples_per_second);
    

    数字音频的世界并非微不足道...一旦有了音频缓冲区,下一步就是将浮点表示转换为可以以字节存储的内容(通常为 16 位整数,具体取决于您选择的位深度) ... 然后需要将 16 位整数缓冲区写为 WAV 文件

    音频是一种有时被称为时间序列的波...当您将拳头捶打在桌子上时,桌子会上下摆动,从而推动微小的空气分子与摆动一致...这种空气的摆动会在房间内传播并到达麦克风膜片或者你的耳膜,它会随着波的共振而摆动……如果你把铅笔粘在膜片上,它会随着膜片一起摇晃,然后你慢慢地沿着铅尖滑动一条纸铅笔你会看到一条曲线被写在纸条上......这是音频曲线......音频样本只是该曲线在某一时刻的高度......如果你反复写下这个曲线高度值以恒定速率每秒 X 次,您将获得原始音频的数据点列表(这是上面的函数创建的)......所以给定的音频样本只是给定时刻的音频曲线高度的值...因为计算机不是连续的,而是磁盘rete 他们无法处理整个铅笔绘制的曲线,所以只关心这个瞬时测量的曲线高度值列表......那些是音频样本

    32 位以上的浮点缓冲区可以输入以下函数以返回 16 位整数缓冲区

    var convert_32_bit_float_into_signed_16_bit_int_lossy = function(input_32_bit_buffer) {
    
        // this method is LOSSY - intended as preliminary step when saving audio into WAV format files
        //                        output is a byte array where the 16 bit output format 
        //                        is spread across two bytes in little endian ordering
    
        var size_source_buffer = input_32_bit_buffer.length;
    
        var buffer_byte_array = new Int16Array(size_source_buffer * 2); // Int8Array 8-bit twos complement signed integer
    
        var value_16_bit_signed_int;
        var index_byte = 0;
    
        console.log("size_source_buffer", size_source_buffer);
    
    
        for (var index = 0; index < size_source_buffer; index++) {
    
            value_16_bit_signed_int = ~~((0 < input_32_bit_buffer[index]) ? input_32_bit_buffer[index] * 0x7FFF : 
                                                                            input_32_bit_buffer[index] * 0x8000);
    
            buffer_byte_array[index_byte] = value_16_bit_signed_int & 0xFF; // bitwise AND operation to pluck out only the least significant byte
    
            var byte_two_of_two = (value_16_bit_signed_int >> 8); //  bit shift down to access the most significant byte
    
            buffer_byte_array[index_byte + 1] = byte_two_of_two;
    
            index_byte += 2;
        };
    
        // ---
    
        return buffer_byte_array;
    };
    

    下一步是将 16 位以上的 int 缓冲区保存到 wav 文件中...我建议您为此使用众多 nodejs 库之一(或者甚至更好地编写自己的库,因为它只有两页代码;-)) )

    【讨论】:

    • 非常感谢您的回答,如果可以的话我想知道我是否可以给出一个频率数组,我也想知道每秒钟的样本是否是每个样本的持续时间?如果您能指导我如何进行 16 位翻译,那就太好了!非常感谢您的回答,这对您有很大帮助。
    • 哇,我学到了很多,感谢您的宝贵时间和精彩的解释。我仍在努力并更好地理解它。你让我对新事物敞开心扉,你是一个伟大的人,也是一个伟大的开发者。谢谢
    猜你喜欢
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多