Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be able to specify a custom audio context / destination + added a gruntfile + automatic compatibility with jspm #1

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict'

module.exports = function(grunt) {

grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-strip');
grunt.loadNpmTasks('grunt-contrib-uglify');

var files = [
'./scripts/gibberish.js',
'./scripts/utils.js',
'./scripts/proxy.js',
'./scripts/oscillators.js',
'./scripts/physical_models.js',
'./scripts/bus.js',
'./scripts/envelopes.js',
'./scripts/analysis.js',
'./scripts/effects.js',
'./scripts/synth.js',
'./scripts/fm_synth.js',
'./scripts/externals/audiofile.js',
'./scripts/sampler.js',
'./scripts/monosynth.js',
'./scripts/binops.js',
'./scripts/time.js',
'./scripts/sequencer_audio.js',
'./scripts/sequencer.js',
'./scripts/input.js',
'./scripts/drums.js',
//__dirname + '/../documentation_output.js',
]

// Project configuration.
grunt.initConfig({

pkg: grunt.file.readJSON('package.json'),

concat: {
dist: {
src: files,
dest: './build/gibberish.js'
}
},
strip : {
main : {
src : '<%= concat.dist.dest %>',
dest : '<%= concat.dist.dest %>',
}
},
uglify: {
options: {
// the banner is inserted at the top of the output
banner: '/*! <%= pkg.name %> v<%= pkg.version %> built on <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'./build/gibberish.min.js': ['<%= strip.main.dest %>']
}
}
},

});

// Default task.
grunt.registerTask('default', ['concat']);
grunt.registerTask('build', ['concat', 'strip', 'uglify']);
};
24 changes: 24 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@

Gibberish is different from other JavaScript audio libraries (such as [audiolib.js][audiolib] or [Audiolet][audiolet]) in that it generates code that is heavily optimized for JIT compilation. The code that is generated is arguably not human-readble, hence the name _Gibberish_. Below is an example of the input code (which you write) and the audio callback that is outputted (which is created by Gibberish... you should never have to even look at this). The audio callback plays a sine wave with vibrato feeding delay and reverb effects:

## This fork

This is a forked version by janesconference. This fork:

- Allows Gibberish to work with an audio node as destination. This allows Gibberish to work in Hyacinth (http://hya.io) and to be more flexible, in general.
- Uses a grunt-based build system and exports a package.json. Just `grunt` to compile gibberish in build/, or `grunt build` to compile, strip logs and uglify.
- Allows Gibbberish to work with jspm.io frictionless package manager (http://jspm.io/)

## Use jspm.io CDN

To get the uglified build from the jspm.io CDN, just put

`https://github.jspm.io/janesconference/Gibberish@master/gibberish.js` in your script tag

or `jspm.import` this URL in your javascript:

`github:janesconference/Gibberish/gibberish`

## Use a custom context and Web Audio Node destination

You can now pass your context and destination audio node to the Gibberish.init() function like this:

`Gibberish.init(your_context, your_audio_node);`

## Live Demo
[http://www.charlie-roberts.com/gibberish][gibberish]

Expand Down
78 changes: 43 additions & 35 deletions scripts/build/gibberish_2.0.js → build/gibberish.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Object. Used in the codegen process to make sure codegen for each ugen is only p
**/


Gibberish = {
window.Gibberish = {
memo : {},
codeblock : [],
analysisCodeblock : [],
Expand Down Expand Up @@ -132,7 +132,7 @@ Perform codegen on all dirty ugens and re-create the audio callback. This method
this.codestring += '}';

this.callbackString = this.codestring;
if( this.debug ) console.log( this.callbackString );
if( this.debug ) 0;

return eval(this.codestring);
},
Expand Down Expand Up @@ -302,45 +302,53 @@ param **readFn** : Function. The audio callback to use.
/**###Gibberish.AudioDataDestination : method
Create a callback and start it running. Note that in iOS audio callbacks can only be created in response to user events. Thus, in iOS this method assigns an event handler to the HTML body that creates the callback as soon as the body is touched; at that point the event handler is removed.
**/
init : function() {
init : function(context, destination, buffersize) {
Gibberish.out = new Gibberish.Bus2();
Gibberish.out.codegen(); // make sure bus is first upvalue so that clearing works correctly
Gibberish.dirty(Gibberish.out);

var bufferSize = typeof arguments[0] === 'undefined' ? 1024 : arguments[0];
var bufferSize = typeof buffersize === 'undefined' ? 1024 : buffersize;

// we will potentially delay start of audio until touch of screen for iOS devices
start = function() {
start = function(context, destination) {

if(navigator.userAgent.indexOf('Firefox') === -1 ){
document.getElementsByTagName('body')[0].removeEventListener('touchstart', start);
if (!context) {
var body = document.getElementsByTagName('body');
if (body && body[0]) {
body[0].removeEventListener('touchstart', start);
}
Gibberish.context = new webkitAudioContext();
Gibberish.node = Gibberish.context.createJavaScriptNode(bufferSize, 2, 2, Gibberish.context.sampleRate);
Gibberish.node.onaudioprocess = Gibberish.audioProcess;
}
else {
// Use the provided context
Gibberish.context = context;
}

Gibberish.node = Gibberish.context.createJavaScriptNode(bufferSize, 2, 2, Gibberish.context.sampleRate);
Gibberish.node.onaudioprocess = Gibberish.audioProcess;

if (!destination) {
Gibberish.node.connect(Gibberish.context.destination);

if('ontouchstart' in document.documentElement){ // required to start audio under iOS 6
}
else {
Gibberish.node.connect(destination);
}

// iOS 6 hack only if the context is not passed in the init function
if (!context) {
if('ontouchstart' in document.documentElement) { // required to start audio under iOS 6
var mySource = Gibberish.context.createBufferSource();
mySource.connect(Gibberish.context.destination);
mySource.noteOn(0);
}
}else{
/*if(typeof AudioContext === 'function') { // use web audio api for firefox 24 and higher... actually, no, it's not fast enough yet
Gibberish.context = new AudioContext();
Gibberish.node = Gibberish.context.createScriptProcessor(1024, 2, 2, Gibberish.context.sampleRate);
Gibberish.node.onaudioprocess = Gibberish.audioProcess;
Gibberish.node.connect(Gibberish.context.destination);
}else{ // use audio data api*/
Gibberish.AudioDataDestination(44100, Gibberish.audioProcessFirefox);
Gibberish.context = { sampleRate: 44100 } // needed hack to determine samplerate in ugens
//}
}

}

if('ontouchstart' in document.documentElement) {
if(!context && 'ontouchstart' in document.documentElement) {
document.getElementsByTagName('body')[0].addEventListener('touchstart', start);
}else{
start();
start(context, destination);
}

return this;
Expand Down Expand Up @@ -885,7 +893,7 @@ Array2.prototype.add = function() {
}
//console.log("ADDING ::: this.parent = ", this.parent)
if(this.parent) {
console.log("DIRTYING");
0;
Gibberish.dirty(this.parent);
}

Expand Down Expand Up @@ -1114,7 +1122,7 @@ Gibberish.Proxy3 = function() {
// return Gibberish.memo[this.symbol];
// }

console.log(" CALLED ")
0
if( ! this.variable ) this.variable = Gibberish.generateSymbol('v');
Gibberish.callbackArgs.push( this.symbol )
Gibberish.callbackObjects.push( this.callback )
Expand Down Expand Up @@ -2009,7 +2017,7 @@ Gibberish.Bus2 = function() {
return panner(output, pan, output);
};

this.show = function() { console.log(output, args) }
this.show = function() { 0 }
this.getOutput = function() { return output }
this.getArgs = function() { return args }

Expand Down Expand Up @@ -2282,7 +2290,7 @@ Gibberish.analysis = function() {
if(this.input.codegen){
input = this.input.codegen()
//console.log( "PROPERTY UGEN", input)
if(input.indexOf('op') > -1) console.log("ANALYSIS BUG")
if(input.indexOf('op') > -1) 0
}else if( this.input.value ){
input = typeof this.input.value.codegen !== 'undefined' ? this.input.value.codegen() : this.input.value
}else{
Expand Down Expand Up @@ -4507,7 +4515,7 @@ WAVDecoder.prototype.decode = function(data) {
var chunk = this.readChunkHeaderL(data, offset);
offset += 8;
if (chunk.name != 'RIFF') {
console.error('File is not a WAV');
0;
return null;
}

Expand All @@ -4517,7 +4525,7 @@ WAVDecoder.prototype.decode = function(data) {
var wave = this.readString(data, offset, 4);
offset += 4;
if (wave != 'WAVE') {
console.error('File is not a WAV');
0;
return null;
}

Expand All @@ -4531,7 +4539,7 @@ WAVDecoder.prototype.decode = function(data) {

if (encoding != 0x0001) {
// Only support PCM
console.error('Cannot decode non-PCM encoded WAV file');
0;
return null;
}

Expand Down Expand Up @@ -4607,7 +4615,7 @@ AIFFDecoder.prototype.decode = function(data) {
var chunk = this.readChunkHeaderB(data, offset);
offset += 8;
if (chunk.name != 'FORM') {
console.error('File is not an AIFF');
0;
return null;
}

Expand All @@ -4617,7 +4625,7 @@ AIFFDecoder.prototype.decode = function(data) {
var aiff = this.readString(data, offset, 4);
offset += 4;
if (aiff != 'AIFF') {
console.error('File is not an AIFF');
0;
return null;
}

Expand Down Expand Up @@ -4788,7 +4796,7 @@ param **buffer** Object. The decoded sampler buffers from the audio file
self.length = phase = bufferLength;
self.isPlaying = true;

console.log("LOADED ", self.file, bufferLength);
0;
Gibberish.audioFiles[self.file] = buffer;

if(self.onload) self.onload();
Expand Down Expand Up @@ -4959,7 +4967,7 @@ _pitch, amp, isRecording, isPlaying, input, length, start, end, loops, pan

if(typeof arguments[0] !== "undefined") {
if(typeof arguments[0] === "string") {
console.log("SETTING FILE");
0;
this.file = arguments[0];
this.pitch = 0;
//this.isPlaying = true;
Expand Down Expand Up @@ -5901,7 +5909,7 @@ function createInput() {
navigator.webkitGetUserMedia(
{audio:true},
function (stream) {
console.log("CONNECTING INPUT");
0;
Gibberish.mediaStreamSource = Gibberish.context.createMediaStreamSource( stream );
Gibberish.mediaStreamSource.connect( Gibberish.node );
_hasInput = true;
Expand Down
3 changes: 3 additions & 0 deletions build/gibberish.min.js

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "Gibberish",
"version": "2.0.1",
"devDependencies": {
"grunt": "~0.4.1",
"grunt-strip": "~0.2.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.4"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/janesconference/Gibberish"
},
"keywords": [
"audio"
],
"bugs": {
"url": "https://github.com/janesconference/Gibberish/issues"
},
"buildConfig": {
"uglify": true
},
"directories": {
"lib": "build"
}
}
16 changes: 0 additions & 16 deletions scripts/build/README.markdown

This file was deleted.

Loading