создание аудиофайла на основе частот - PullRequest
1 голос
/ 02 августа 2020

Я использую node.js для проекта, над которым я работаю. Проект состоит в том, чтобы преобразовать слова в числа, а затем взять эти числа и создать аудиовыход. Аудиовыход должен воспроизводить числа как частоты. например, у меня есть массив чисел [913, 250,352], теперь я хочу воспроизвести эти числа как частоты. Я знаю, что могу воспроизводить их в браузере с аудио API или любым другим третьим пакетом, который позволяет мне это делать. Дело в том, что я хочу создать какой-то аудиофайл, я попытался преобразовать эти числа в заметки, а затем сохранить его как файл Midi, мне это удалось, но проблема в том, что файл midi принимает частоты, конвертирует их в ближайшую заметку (пример : 913 преобразуется в 932,33 Гц (номер примечания 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()))

Я искал inte rnet, но не нашел ничего, что могло бы помочь. Я действительно хочу иметь файл, который пользователь может загрузить с этими числами в качестве частот, кто-нибудь знает, что можно сделать, чтобы получить такой результат?

Заранее спасибо за помощников.

1 Ответ

1 голос
/ 03 августа 2020

эта функция заполнит буфер значениями с плавающей запятой, которые представляют высоту необработанной звуковой кривой для данной частоты

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 file

звук - это волна, которую иногда называют временным рядом ... когда вы ударяете кулаком по столу, стол качается вверх и вниз, толкая крошечные молекулы воздуха в унисон с этим колебанием ... это колебание воздуха распространяется по комнате и достигает диафрагмы микрофона или, может быть, вашей барабанной перепонки, которая, в свою очередь, колеблется в резонансе с этой волной ... если вы приклеили карандаш к диафрагме, так что она качалась вместе с диафрагмой, и вы медленно скользили полосой бумаги по ней. грифель карандаша вы w я бы увидел, как кривая записывается на эту бумажную полоску ... это звуковая кривая ... звуковой образец - это просто высота этой кривой в данный момент времени ... если вы неоднократно записывали это значение высоты кривой X раз в секунду с постоянной скоростью у вас будет список точек данных необработанного звука (это то, что создает вышеупомянутая функция) ... таким образом, данный образец звука - это просто значение высоты звуковой кривой в данный момент времени .. .поскольку компьютеры не являются непрерывными, а дискретны, они не могут обрабатывать всю нарисованную карандашом кривую, поэтому заботьтесь только об этом списке мгновенно измеренных значений высоты кривой ... это аудиосэмплы

выше 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-битного целочисленного буфера в wav-файле ... Я предлагаю вам использовать одну из многих nodejs библиотек для что (или еще лучше написать свой собственный код на двух страницах; -)))

...