2
\$\begingroup\$

I'm trying to figure out a way to have cleaner, efficient code for a web audio project i've been working on. the code I have right now is this:

//OSCILLATOR INFO//
// Oscillator Pitch is in Hz.
// Oscillator Detune is in Cents & can be positive or negative values. 
// 1 Octave = double/half the note frequency in Hz. (A3 = 220Hz; A4 = 440Hz; A5 = 880Hz)
// 1 Octave = 1200 Cents. 100 Cents per Semitone. (A3 - A4 = 1200 Cents; A4 - A5 = 1200 Cents)
// 12 Semitones per Octave.
// (A-440Hz detuned by 100 cents = A#; detuned by -100 cents = Ab)
//JQUERY SET UP//
//WEB AUDIO SET UP//
//used start web audio
var ctx = new webkitAudioContext();
speakers = ctx.destination;
var osc1 = ctx.createOscillator();
var osc2 = ctx.createOscillator();
var osc3 = ctx.createOscillator();
$(document).ready(function () {
    //WAVEFORM OBJECTS - used to set the value of "cur_wave_osc" under Waveform sliders.//
    var wF = {
        0: "Sine",
        1: "Square",
        2: "Sawtooth",
        3: "Triangle"
    };
    //PLAY_PAUSE BUTTONS - used to play & pause the oscillators.//
    //OSC1 PLAY_PAUSE//
    $('#play_pause_osc1').click(function () {
        if ($(this).val() == "Play Osc1") {
            $(this).val("Pause");
            oscillator1Start();
        } else {
            $(this).val("Play Osc1");
            osc1.disconnect();
        }
    });
    //OSC2 PLAY_PAUSE//
    $('#play_pause_osc2').click(function () {
        if ($(this).val() == "Play Osc2") {
            $(this).val("Pause");
            oscillator2Start();
        } else {
            $(this).val("Play Osc2");
            osc2.disconnect();
        }
    });
    //OSC3 PLAY_PAUSE//
    $('#play_pause_osc3').click(function () {
        if ($(this).val() == "Play Osc3") {
            $(this).val("Pause");
            oscillator3Start();
        } else {
            $(this).val("Play Osc3");
            osc3.disconnect();
        }
    });
    //GAIN SLIDERS - used for controlling osc volume.//
    //OSC1_GAIN//
    $(function () {
        $("#osc1_vol").slider({
            min: 0,
            max: 1,
            value: 0.5,
            step: 0.01,
            slide: function (event, ui) {
                $("#cur_vol_osc1").val(ui.value);
                gainNode1.gain.value = $("#cur_vol_osc1").val();
            }
        });
        $("#cur_vol_osc1").val($("#osc1_vol").slider("value"));
    });
    //OSC2_GAIN//
    $(function () {
        $("#osc2_vol").slider({
            min: 0,
            max: 1,
            value: 0.5,
            step: 0.01,
            slide: function (event, ui) {
                $("#cur_vol_osc2").val(ui.value);
                gainNode2.gain.value = $("#cur_vol_osc2").val();
            }
        });
        $("#cur_vol_osc2").val($("#osc2_vol").slider("value"));
    });
    //OSC3_GAIN//
    $(function () {
        $("#osc3_vol").slider({
            min: 0,
            max: 1,
            value: 0.5,
            step: 0.01,
            slide: function (event, ui) {
                $("#cur_vol_osc3").val(ui.value);
                gainNode3.gain.value = $("#cur_vol_osc3").val();
            }
        });
        $("#cur_vol_osc3").val($("#osc3_vol").slider("value"));
    });
    //PITCH SLIDERS - used for controlling osc pitch.//
    //OSC1_PITCH//
    $(function () {
        $("#osc1_pitch").slider({
            min: 0,
            max: 25000,
            value: 440,
            step: 1,
            slide: function (event, ui) {
                $("#cur_pitch_osc1").val(ui.value);
                osc1.frequency.value = $("#cur_pitch_osc1").val();
            }
        });
        $("#cur_pitch_osc1").val($("#osc1_pitch").slider("value"));
    });
    //OSC2_PITCH//
    $(function () {
        $("#osc2_pitch").slider({
            min: 0,
            max: 25000,
            value: 440,
            step: 1,
            slide: function (event, ui) {
                $("#cur_pitch_osc2").val(ui.value);
                osc2.frequency.value = $("#cur_pitch_osc2").val();
            }
        });
        $("#cur_pitch_osc2").val($("#osc2_pitch").slider("value"));
    });
    //OSC3_PITCH//
    $(function () {
        $("#osc3_pitch").slider({
            min: 0,
            max: 25000,
            value: 440,
            step: 1,
            slide: function (event, ui) {
                $("#cur_pitch_osc3").val(ui.value);
                osc3.frequency.value = $("#cur_pitch_osc3").val();
            }
        });
        $("#cur_pitch_osc3").val($("#osc3_pitch").slider("value"));
    });
    //DETUNE SLIDER - used for controlling osc detune.//
    //OSC1_DETUNE//
    $(function () {
        $("#osc1_detune").slider({
            min: -4800,
            max: 4800,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_detune_osc1").val(ui.value);
                osc1.detune.value = $("#cur_detune_osc1").val();
            }
        });
        $("#cur_detune_osc1").val($("#osc1_detune").slider("value"));
    });
    //OSC2_DETUNE//
    $(function () {
        $("#osc2_detune").slider({
            min: -4800,
            max: 4800,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_detune_osc2").val(ui.value);
                osc2.detune.value = $("#cur_detune_osc2").val();
            }
        });
        $("#cur_detune_osc2").val($("#osc2_detune").slider("value"));
    });
    //OSC3_DETUNE//
    $(function () {
        $("#osc3_detune").slider({
            min: -4800,
            max: 4800,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_detune_osc3").val(ui.value);
                osc3.detune.value = $("#cur_detune_osc3").val();
            }
        });
        $("#cur_detune_osc3").val($("#osc3_detune").slider("value"));
    });
    //WAVEFORM SLIDERS - used for selecting osc waveform.//
    //OSC1_WAVEFORM//
    $(function () {
        $("#osc1_wave").slider({
            min: 0,
            max: 3,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_wave_osc1").val(wF[ui.value]);
            }
        });
        $("#cur_wave_osc1").val("Sine");
        osc1.type = $("#osc1_wave").slider("value");
    });
    //OSC2_WAVEFORM//
    $(function () {
        $("#osc2_wave").slider({
            min: 0,
            max: 3,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_wave_osc2").val(wF[ui.value]);
            }
        });
        $("#cur_wave_osc2").val("Sine");
        osc2.type = $("#osc2_wave").slider("value");
    });
    //OSC3_WAVEFORM//
    $(function () {
        $("#osc3_wave").slider({
            min: 0,
            max: 3,
            value: 0,
            step: 1,
            slide: function (event, ui) {
                $("#cur_wave_osc3").val(wF[ui.value]);
            }
        });
        $("#cur_wave_osc3").val("Sine");
        osc3.type = $("#osc3_wave").slider("value");
    });
});
//CREATE OSCILLATORS//
//OSC1//
function oscillator1Start() {
    //creates the osc
    osc1 = ctx.createOscillator();
    //sets waveform
    osc1.type = $("#osc1_wave").slider("value"); //0 = sine, 1 = square, 2 = saw, 3 = triangle, 4 = custom
    //sets frequency
    osc1.frequency.value;
    //sets detune
    osc1.detune.value;
    //creates a gain node
    gainNode1 = ctx.createGainNode();
    //connects osc to gain node
    osc1.connect(gainNode1);
    //connects gain node to speakers
    gainNode1.connect(speakers);
    //sets gain value
    gainNode1.gain.value;
    //plays the osc
    osc1.start(0);
}
//OSC2//
function oscillator2Start() {
    //creates the osc
    osc2 = ctx.createOscillator();
    //sets waveform
    osc2.type; //0 = sine, 1 = square, 2 = saw, 3 = triangle, 4 = custom
    //sets frequency
    osc2.frequency.value;
    //sets detune
    osc2.detune.value;
    //creates a gain node
    gainNode2 = ctx.createGainNode();
    //connects osc to gain node
    osc2.connect(gainNode2);
    //connects gain node to speakers
    gainNode2.connect(speakers);
    //sets gain value
    gainNode2.gain.value;
    //plays the osc
    osc2.start(0);
}
//OSC3//
function oscillator3Start() {
    //creates the osc
    osc3 = ctx.createOscillator();
    //sets waveform
    osc3.type; //0 = sine, 1 = square, 2 = saw, 3 = triangle, 4 = custom
    //sets frequency
    osc3.frequency.value;
    //sets detune
    osc3.detune.value;
    //creates a gain node
    gainNode3 = ctx.createGainNode();
    //connects osc to gain node
    osc3.connect(gainNode3);
    //connects gain node to speakers
    gainNode3.connect(speakers);
    //sets gain value
    gainNode3.gain.value;
    //plays the osc
    osc3.start(0);
}

it seems like I have a lot of repetitive code so I was considering making some constructors for things like creating a a new osc or play/pause button. The problem I'm running into though, is since my oscillator controls are controlled via jquery how would i still use my jQuery sliders, buttons in the constructors?

This is as far as I've gotten:

var ctx = new webkitAudioContext();
//object constructor
function Osc(type,freq,detune,gain)
{
    this.create = new ctx.createOscillator();
    this.type = type; //0 = sine, 1 = square, 2 = saw, 3 = triangle, 4 = custom
    this.freq = freq;
    this.detune = detune;
    this.gain = gain;
    this.changeType = changeType;
    function changeType(type)
    {
        this.type = type;
    };
    this.changeFreq = changeFreq;
    function changeFreq(freq)
    {
        this.freq = freq;
    };
}

Any help is appreciated!

\$\endgroup\$
2
\$\begingroup\$

I just picked one part of the code that could use some polishing. Consider the following :

$('#play_pause_osc1').click(function () {
    if ($(this).val() == "Play Osc1") {
        $(this).val("Pause");
        oscillator1Start();
    } else {
        $(this).val("Play Osc1");
        osc1.disconnect();
    }
});

You are switching here from one label back to another in a cycle, and then also do something. You do this for a ton of click listeners. You could do something like

function switchButton( $button, label1, label2, function1, function2 )
{
  if( $button.val() == label1 )
  {
    $(this).val( label2 );
    function1();   
  }
  else
  {
    $(this).val( label1 );
    function2();   
  }
}

$('#play_pause_osc1').click( function() 
{ 
  switchButton( "Play Osc1" , "Pause" , oscillator1Start ,  osc1.disconnect );
});
$('#play_pause_osc2').click( function() 
{
  switchButton( "Play Osc2" , "Pause" , oscillator2Start ,  osc2.disconnect );
});
$('#play_pause_osc3').click( function() 
{
  switchButton( "Play Osc3" , "Pause" , oscillator3Start ,  osc3.disconnect );
});

This is much less code, but it is obvious that you still have copy pasted code. It is also obvious that your oscillators should be in an array.

On a final note, are you sure your code is working ? The following statements do completely nothing, and they are part of your oscillatornStart:

   //sets frequency
   osc1.frequency.value;
   //sets detune
   osc1.detune.value;
   //sets gain value
   gainNode1.gain.value;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.