audiojs / audio-oscillator

Generate periodic oscillation into an array/audiobuffer
MIT License
27 stars 2 forks source link

Playing for a specific time #24

Closed RossComputerGuy closed 5 years ago

RossComputerGuy commented 7 years ago

I am wondering if there is a way to have a sound be generated for a specific amount of time. Example: I could have the program oscillate a sound for 5 minutes or 6 days. This is for a virtual machine that I'm building. My code:

const createOscillator = require("audio-oscillator");
const createSpeaker = require("audio-speaker");
const IO = require(__dirname+"/../../io");
const OSCILLATOR_TYPES = [
    "sine","sin",
    "cosine","cos",
    "saw","sawtooth",
    "tri","triangle",
    "rect","rectangle","quad","square",
    "delta","pulse",
    "series","fourier","harmonics","periodic",
    "clausen",
    "step",
    "interpolate",
    "noise"
];
const Speaker = require("audio-speaker/pull");

function Audio(vm) {
    this.vm = vm;
    this.buffer = [];

    this.oscillator = {};
    this.oscillator.type = "sine";
    this.oscillator.frequency = 440;
    this.oscillator.detune = 0;
    this.oscillator.sampleRate = 44100;
    this.oscillator.channels = 1;
    this.oscillator.dtype = "array";
    this.oscillator.phase = 0;

    this.vm.io.ports[0xA2] = new IO(0xA2,this.vm);
    this.vm.io.ports[0xA3] = new IO(0xA3,this.vm);

    this.vm.io.ports[0xA2].on("write16",(value) => {
        switch(value) {
            case 0:
                this.buffer = [];
                break;
            case 12:
                process.nextTick(() => {
                    var oscillator = createOscillator(this.oscillator);
                    console.log(createSpeaker(oscillator));
                });
                break;
            default:
                this.vm.io.ports[0xA2].value = value;
                break;
        }
    });
    this.vm.io.ports[0xA3].on("write16",(value) => {
        switch(this.vm.io.ports[0xA2].value) {
            case 1:
                this.buffer.push(value);
                break;
            case 2:
                this.buffer.splice(value,1);
                break;
            case 3:
                this.oscillator.type = OSCILLATOR_TYPES[value];
                switch(this.oscillator.type) {
                    case "sine":
                    case "sin":
                        this.oscillator.phase = 0;
                        break;
                    case "cosine":
                    case "cos":
                        this.oscillator.phase = 0;
                        break;
                    case "saw":
                    case "sawtooth":
                        this.oscillator.inversed = false;
                        break;
                    case "tri":
                    case "triangle":
                        this.oscillator.ratio = 0.5;
                        break;
                    case "rect":
                    case "rectangle":
                    case "quad":
                    case "square":
                        this.oscillator.ratio = 0.5;
                        break;
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.real = [0,1];
                        this.oscillator.imag = [0,0];
                        this.oscillator.normalize = true;
                        break;
                    case "clausen":
                        this.oscillator.limit = 10;
                        break;
                    case "step":
                        this.oscillator.samples = [];
                        break;
                    case "interpolate":
                        this.oscillator.samples = [];
                        break;
                }
                break;
            case 4:
                this.oscillator.frequency = value;
                break;
            case 5:
                this.oscillator.detune = value;
                break;
            case 6:
                this.oscillator.sampleRate = value;
                break;
            case 7:
                switch(this.oscillator.type) {
                    case "sine":
                    case "sin":
                        this.oscillator.phase = value;
                        break;
                    case "cosine":
                    case "cos":
                        this.oscillator.phase = value;
                        break;
                    case "saw":
                    case "sawtooth":
                        this.oscillator.inverted = (value == 1);
                        break;
                    case "tri":
                    case "triangle":
                        this.oscillator.ratio = value;
                        break;
                    case "rect":
                    case "rectangle":
                    case "quad":
                    case "square":
                        this.oscillator.ratio = value;
                        break;
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.real[0] = value;
                        break;
                    case "clausen":
                        this.oscillator.limit = value;
                        break;
                    case "step":
                    case "interpolate":
                        this.oscillator.samples.push(value);
                        break;
                }
                break;
            case 8:
                switch(this.oscillator.type) {
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.real[1] = value;
                        break;
                }
                break;
            case 9:
                switch(this.oscillator.type) {
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.imag[0] = value;
                        break;
                }
                break;
            case 10:
                switch(this.oscillator.type) {
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.imag[1] = value;
                        break;
                }
                break;
            case 11:
                switch(this.oscillator.type) {
                    case "series":
                    case "fourier":
                    case "harmonics":
                    case "periodic":
                        this.oscillator.normalize = (value == 1);
                        break;
                }
                break;
        }
    });
}

module.exports = Audio;
dy commented 7 years ago

@SpaceboyRoss01 simplest way for now is counting generated data - every time you generate a buffer, you require a number of samples, ie.

let n = 1024
let buf = oscillate(n);
count += n;

//if more than 6 days - abort
let sixDays = 44100*6*24*60*60
if (count > sixDays) oscillate(null)
RossComputerGuy commented 7 years ago

but that doesn't play the sound to the speaker

dy commented 7 years ago

Well that was not the question :) Just output the generated data to the speaker that's it. I'll try to come up with more elaborate example once https://github.com/audiojs/audio-speaker/pull/44 is released.

dy commented 5 years ago

Not sure what is the issue here. Pls let me know if that is still actual.