I am hoping to implement audio effects in the Web Audio API which require continuous access to two or more audio streams.
I can define a script processor with 2 input channels and 2 output channels:
var mod = context.createScriptProcessor(4096,2,2);
I can then connect a few sine waves to this processor:
mySine.connect(mod);
mySine2.connect(mod);
Is there a way to connect them to a specific input channel of the audio processor?
Eventually, when I write an onaudioprocess function and listen to each input channel individually, each input channel contains all the sounds connected to the processor. I have no way to access each sine wave individually within the onaudioprocess function. Is this correct? Or is there a way to connect sounds to a single input channel of the scriptprocessor?
You could either create two identical single channel ScriptProcessors or maybe use a channel merger to assign the two sine waves to each channel of the script processor like this:
var context = new AudioContext();
var sineA = context.createOscillator();
sineA.type = 'sine';
sineA.frequency.value = 300;
var sineB = context.createOscillator();
sineB.type = 'sine';
sineB.frequency.value = 100;
var script = context.createScriptProcessor(4096, 2, 2);
// create 2 channel merger node
var merger = context.createChannelMerger(2);
// connect sineA to channel 0
sineA.connect(merger, 0, 0);
// connect sineA to channel 1
sineB.connect(merger, 0, 1);
// connect the script to the merger
merger.connect(script);
// process the audio data of each channel
script.onaudioprocess = function(event) {
var input = event.inputBuffer;
var output = event.outputBuffer;
var inputA = input.getChannelData(0);
var inputB = input.getChannelData(1);
var outputA = output.getChannelData(0);
var outputB = output.getChannelData(1);
for (var i = 0; i < input.length; i++) {
outputA[i] = inputA[i];
outputB[i] = inputB[i];
}
}
script.connect(context.destination);
sineA.start();
sineB.start();
Related
I am using this spectrogram.js from github to plot spectrogram and obtain frequency values in real-time.
Github Repo
I have written this extra stopSong function:
function stopSong() {
var analyser = audioContext.createAnalyser();
var ctx = new AudioContext();
var osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
spectro.stop();
var freqData= new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
//var f = Math.round(freqData[1]);
// var text = f + ' Hz';
var idx = 0;
for (var j=0; j < analyser.frequencyBinCount; j++) {
if (freqData[j] > freqData[idx]) {
idx = j;
}
}
var frequency = idx * ctx.sampleRate / analyser.fftSize;
console.log(frequency);
//document.getElementById("frec").innerHTML = text;
}
But everytime i am running it it give 0 as output. Can anybody tell whats wrong with my code.
You need to connect the oscillator to the analyser:
oscillator.connect(analyser);
Also you might want to call getByteFrequencyData multiple times, maybe in requestAnimationFrame, or something like setTimeout.
I work in theoretical physics and I do lot of computer simulations. An important part of my duty is the analysis of the results. I make simulations and store the numerical results in a file with some simple name. Typically I have lot of data files with very similar name and after a while I do not remember what kind of parameters the file corresponds to. I was thinking that maybe there exists a better way to store numerical results from a simulation e.g. some database (SQL, MongoDB etc.) where I could put some comments about parameters of the program, names, date etc. - a sort of a library with numerical data. I just have everything in a one place well organized. Do you know of anything like this? How do you store you numerical data from computer simulations?
More details
Typical procedure looks like this. Let say we want to simulate time evolution of the three body problem. We have three bodies of different masses interacting with Newton forces. I want to test how these objects move in space depending on: relative mass value, initial position - 6 parameters. I run simulation for one choice of parameters and save it in file: three_body_m1=0p1_m2=0p3_(the rest).dat - all double precision in total 1+3*3 (3d) columns of data in one file. Then I lunch gnuplot, python etc. and visualize them. In principle there is no relation between the data from different simulations, but I can use them to make comparison plot.
Within same nodejs context, you can,
Stream big xyz data file to server using socket.io-stream + fs modules and save filename+parameters to database using mongodb module.(max 1-page of coding but more for complex server talking)
If data fits in ram and if you don't have to save immediately, you can use redis module to send everything to server cache easily(as key-value pairs such as data->xyzData and parameters->simulationParameters and user->name_surname) and read from it high speed. If you need data as file by other processes in server, you can stram to a ramdisk instead and have most of RAM bandwidth as a file cache.(needs more ram ofcourse but fast)
mongodb is slow(even with optimizations) for saving millions of particles xyz data but is most easiest and quickest install for parameter saving and sharing.
Using all could be better.
Saving: stream file to physical disk using socket.io-stream and fs. Send parameters to mongodb.
Loading: check redis if user is registered, check if data is in cache, if yes, get it, if no, stream from physical disk and also save some of it to redis at the same time.
Editing: check if cache exists, if yes then edit it. Another serverside process can update physical disk from that cache, if no then update physical disk directly.
The communication scheme could be:
data server talks to cache server if there is any pending writes/reads/edits, consumes jobs from there.
compute server talks to cache server for producing read/write/edit jobs or consuming compute jobs.
clients can talk to cache server for reading only.
admins can also place their own data or produce compute jobs or read stuff.
compute server, data server and cache server can be on same computer easily or moved to other computers thanks to nodejs's awesomeness and countless modules of it such as redis, socket.io-stream, fs, ejs, express(for clients for example), etc.
a cache server can offload some data to another cache server and have a redirection to it(or some mapping of data to it)
a cache server can communicate N number of data servers and M number of compute servers at the same time as long as RAM holds.
You have slow network? You can use gzip module to compress the data on-the-fly with just 3-5 lines of extra code(at both ends)
You don't have money?
Nodejs works on raspberry pi (as data server maybe?)
Nvidia GTX660 can work with an Intel galileo (compute server?) using nodejs with some extra native modules for opencl(could be hard to implement)(also connecting(and powering) gpu and galileo may not be easy but should be much faster than a cluster of raspberry pi boards for fp32 number crunching)
bypass cache, RAM is expensive for now.
data server cluster
\
\
\ client
\ client /
\ / /
\ / /
mainframe cache and database server ----- compute cluster
| \
| \
support cache server admin
A very simple example to send some files to another computer(or same):
var pipeline_n = 8;
var fs = require("fs");
// server part accepting files
{
var io = require('socket.io').listen(80);
var ss = require('socket.io-stream');
var path = require('path');
var ctr = 0;
var ctr2 = 0;
io.of('/user').on('connection', function (socket) {
var z1 = new Date();
for (var i = 0; i < pipeline_n; i++) {
ss(socket).on('data'+i.toString(), function (stream, data) {
var t1 = new Date();
stream.pipe(fs.createWriteStream("m://bench_server" + ctr + ".txt"));
ctr++;
stream.on("finish", function (p) {
var len = stream._readableState.pipes.bytesWritten;
var t2 = new Date();
ctr2++;
if (ctr2 == pipeline_n) {
var z2 = new Date();
console.log(len * pipeline_n);
console.log((z2 - z1));
console.log("throughput: " + ((len * pipeline_n) / ((z2 - z1)/1000.0))/(1024*1024)+" MB/s");
}
});
});
}
});
}
//client or another server part sending a file
//(you can change it to do parts of same file instead of same file n times),
//just a dummy file sending code to stress other server
for (var i = 0; i < pipeline_n; i++)
{
var io = require('socket.io-client');
var ss = require('socket.io-stream');
var socket = io.connect('http://127.0.0.1/user');
var stream = ss.createStream();
var filename = 'm://bench.txt'; // ramdrive or cluster of hdd raid
ss(socket).emit('data'+i.toString(), stream, { name: filename });
fs.createReadStream(filename).pipe(stream);
}
Here is testing insert vs bulk insert performance of mongodb(this could be a wrong way to benchmark but is simple, just uncomment-in the part you want to benchmark)
var mongodb = require('mongodb');
var client = mongodb.MongoClient;
var url = 'mongodb://localhost:2019/evdb2';
client.connect(url, function (err, db) {
if (err) {
console.log('fail:', err);
} else {
console.log('success:', url);
var collection = db.collection('tablo');
var bulk = collection.initializeUnorderedBulkOp();
db.close();
//benchmark insert
//var t = 0;
//t = new Date();
//var ctr = 0;
//for (var i = 0; i < 1024 * 64; i++)
//{
// collection.insert({ x: i + 1, y: i, z: i * 10 }, function (e, r) {
// ctr++;
// if (ctr == 1024 * 64)
// {
// var t2 = 0;
// db.close();
// t2 = new Date();
// console.log("insert-64k: " + 1000.0 / ((t2.getTime() - t.getTime()) / (1024 * 64)) + " insert/s");
// }
// });
//}
// benchmark bulk insert
//var t3 = new Date();
//for (var i = 0; i < 1024 * 64; i++)
//{
// bulk.insert({ x: i + 1, y: i, z: i * 10 });
//}
//bulk.execute();
//var t4 = new Date();
//console.log("bulk-insert-64k: " + 1000.0/((t4.getTime() - t3.getTime()) / (1024 * 64)) + " insert/s");
// db.close();
}
});
be sure to setup mongodb and or redis servers before this. Also "npm install module_name" necessary modules from nodejs command prompt.
I'm facing an issue with Mirthconnect.
I just have a trouble in this process. I like to read the data from mail, is it possible to acheive this in the open source mirthconnect? of version 3.3.1, if so is it possible to read from direct mail?. Apart from the commerical versions like mirth mails.
I made use of JAVA mail library and inserted it in the custom library folder of mirth connect then used the following code in the connector portion of mirth. It works well.
//Fetchmail from Gmail
var props = new Packages.java.util.Properties();
props.setProperty("mail.store.protocol", "imaps");
var session = new Packages.javax.mail.Session.getInstance(props, null);
var store = session.getStore();
store.connect("imap.gmail.com", "xxxxxxxx#gmail.com", "xxxxxxxxx");
var inbox = store.getFolder("INBOX");
inbox.open(Packages.javax.mail.Folder.READ_ONLY);
var msgs = inbox.getMessage(inbox.getMessageCount());
var currentMessage = inbox.getMessage(inbox.getMessageCount());
var mp = currentMessage.getContent();
var bp = mp.getBodyPart(0);
var content = "" + bp.getContent();
content = content.replace(/''/g, "");
globalMap.put('gcon', content);
logger.info("SENT DATE:" + msgs.getSentDate());
logger.info("SUBJECT:" + msgs.getSubject());
logger.info("CONTENT:" + content);
//bp.getContent()
var receiveId = UUIDGenerator.getUUID();
logger.info("incomingMailID : "+receiveId);
//Database Connectivity
var time= msgs.getSentDate();
var con = bp.getContent();
var sub = msgs.getSubject();
//global variable declaration
globalMap.put('glcontent',con);
globalMap.put('glsubject',sub);
globalMap.put('gltime',time);
return sub;
Then you can set the the polling frequency time intervalin the listener which the mirth channel will poll for that specific time interval.
I have blob type generated by webaudio API, but the file that is saved have to high sample rate.
How can I convert it to lower maybe something like https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext can help?
Here is some sample of code:
var xhr = new XMLHttpRequest();
/* HERE IS SOME CONVERTATION TO LOWER RATE */
var fd = new FormData();
fd.append("randomname", bigBlob);
xhr.open("POST",url,false);
xhr.send(fd);
xhr.onload=function(e) {
alert(e.target.responseText);
};
Create an OfflineAudioContext with the rate you want at the end, and the number of frames there will be at the end
Create an AudioBuffer from your raw data buffer
Create an AudioBufferSourceNode, set its buffer attribute to the AudioBuffer you just created, and connect this AudioBufferSourceNode to the destination of the OfflineAudioContext
Start the AudioBufferSourceNode at 0
Start the rendering
I couldn't find a way to control the sample rate but here is a way to re-sample (up/down sampling)
function reSample(audioBuffer, targetSampleRate, onComplete) {
var channel = audioBuffer.numberOfChannels;
var samples = audioBuffer.length * targetSampleRate / audioBuffer.sampleRate;
var offlineContext = new OfflineAudioContext(channel, samples, targetSampleRate);
var bufferSource = offlineContext.createBufferSource();
bufferSource.buffer = audioBuffer;
bufferSource.connect(offlineContext.destination);
bufferSource.start(0);
offlineContext.startRendering().then(function(renderedBuffer){
onComplete(renderedBuffer);
})
}
Extracted from here:
https://github.com/notthetup/resampler
Hi im trying to export the Emailadresses from the senders in a label in Gmail Called "Suarez". But it's just running and never completing, it should be about 372 emails. Is it to much to print to the logger?
Here is what im trying:
function getEmailsadresses(){
var threads = GmailApp.search("in:suarez");
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var m = 0; m < messages.length; m++) {
var msg = messages[m].getFrom();
}
}
Logger.log(msg()); // log from address of the message
}
I use a script embedded in an spreadsheet the reads every messages in every threads in a Label that could probably be a good starting point for you.
My specific use case was to log SMS messages that my android phone sends me as emails each time I send or receive a text message.
So it will work for you by just changing the label name and maybe remove the data filtering I added on the message. Since I have a lot of data I set up a time trigger task manager to works in small bunches to avoid exceeding time limit.
Usage is simple : run the "startSMSLog" and go have a couple of coffees until the cell A1 in the spreadsheet stops being RED... that's it.
Code below : the start function
function startSMSLog(){
var triggerID = ScriptApp.newTrigger('countSMSLogEmails').timeBased().everyMinutes(5).create().getUniqueId();
var thisTrigger = PropertiesService.getScriptProperties().setProperty('thisTriggerSMS',triggerID);
PropertiesService.getScriptProperties().setProperty('current thread SMS',0);
var sh = SpreadsheetApp.getActive().getSheetByName('SMS'); // change to the name of your sheet
sh.getRange('A1').setBackground('red');
countSMSLogEmails(true);
}
and the "working" code :
function countSMSLogEmails(clearSheet){
var sh = SpreadsheetApp.getActive().getSheetByName('SMS');
var start = Number(PropertiesService.getScriptProperties().getProperty('current thread SMS'));
var CallLogThreads = GmailApp.getUserLabelByName('SMS').getThreads(start,10);
if(CallLogThreads.length==0){
sh.sort(2,false);
sh.getRange('A1').setBackground('#FFC');
var triggers = ScriptApp.getProjectTriggers();
var thisTrigger = PropertiesService.getScriptProperties().getProperty('thisTriggerSMS');
for(var n in triggers){
if(triggers[n].getUniqueId()==thisTrigger){ScriptApp.deleteTrigger(triggers[n])};
}
sh.getRange('A1').setValue('Subject (Log on '+Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd-MMM-yy HH:mm")+')');
return;
} else {
PropertiesService.getScriptProperties().setProperty('current thread SMS',start+CallLogThreads.length);
}
var data = [];
for(var n=0;n<CallLogThreads.length;n++){
var thread = CallLogThreads[n];
Logger.log('thread message count = '+thread.getMessageCount());
var msg = thread.getMessages();
var msgData = [];
for(var m in msg){
var msgDate = msg[m].getDate();
var msgSubject = msg[m].getSubject();
var msgBody = msg[m].getBody().replace(/[\n\r]/g,' ').replace(/'/g,"'").replace(/ /g,"!").replace(/&/g,"&").replace(/"/g,'"')
.replace(/>/g,'>').replace(/</g,'<').replace(/<br \/>/g,'\n').replace(/<br>/g,'\n');
msgData.push([msgSubject,msgDate,msgBody]);
}
data.push(msgData);
}
var dataTotal = [];
if (clearSheet==true) {
dataTotal.push(['subject', 'date', 'message']);
}
for(var n in data){
dataTotal = dataTotal.concat(data[n]);
};
Logger.log(JSON.stringify(dataTotal));
if (clearSheet==true) {
sh.clearContents();
sh.getRange(1,1,dataTotal.length,dataTotal[0].length).setValues(dataTotal);
}else{
sh.getRange(sh.getLastRow()+1,1,dataTotal.length,dataTotal[0].length).setValues(dataTotal);
}
}