I managed to record and play my voice like a dictaphone thanks to Cordova. Now i would like to add an "Autotune" or "Vocoder" effect on my voice, how can i do that ?
PS:I work on mobile device.
Here is the the script for record and play my voice :
<script type="text/javascript" charset="utf-8" src="cordova-1.7.0rc1.js"></script>
<script type="text/javascript" src="jquery-1.7.1.js"></script>
<script type="text/javascript">
var deviceready = false;
var mediaVar = null;
var recordFileName = "recording.wav";
var status = null;
var isIOS = false;
function onBodyLoad()
{
document.addEventListener("deviceready", onDeviceReady, false);
deviceready = true;
}
$(document).ready(function(){
$("#stopBtn").hide();
$("#playBtn").hide();
//validation to check if device is ready is skipped
$("#recordBtn").click(function(){
record();
});
$("#playBtn").click(function(){
play();
});
$("#stopBtn").click(function(){
stop();
});
});
function record()
{
createMedia(function(){
status = "recording";
mediaVar.startRecord();
$("#recordBtn").hide();
$("#stopBtn").show();
$("#playBtn").hide();
},onStatusChange);
}
function createMedia(onMediaCreated, mediaStatusCallback){
if (mediaVar != null) {
onMediaCreated();
return;
}
if (typeof mediaStatusCallback == 'undefined')
mediaStatusCallback = null;
if (isIOS) {
//first create the file
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(recordFileName, {
create: true,
exclusive: false
}, function(fileEntry){
log("File " + recordFileName + " created at " + fileEntry.fullPath);
mediaVar = new Media(fileEntry.fullPath, function(){
log("Media created successfully");
}, onError, mediaStatusCallback); //of new Media
onMediaCreated();
}, onError); //of getFile
}, onError); //of requestFileSystem
} else //it's Android
{
mediaVar = new Media(recordFileName, function(){
log("Media created successfully");
}, onError, mediaStatusCallback);
onMediaCreated();
}
}
function stop()
{
if (mediaVar == null)
return;
if (status == 'recording')
{
mediaVar.stopRecord();
log("Recording stopped");
}
else if (status == 'playing')
{
mediaVar.stop();
log("Play stopped");
}
else
{
log("Nothing stopped");
}
$("#recordBtn").show();
$("#stopBtn").hide();
$("#playBtn").show();
status = 'stopped';
}
function play()
{
createMedia(function(){
status = "playing";
mediaVar.play();
$("#recordBtn").hide();
$("#stopBtn").show();
$("#playBtn").hide();
});
}
function onStatusChange()
{
if (arguments[0] == 4) //play stopped
{
$("#recordBtn").show();
$("#stopBtn").hide();
$("#playBtn").show();
}
}
function onSuccess()
{
//do nothing
}
function onError(err)
{
if (typeof err.message != 'undefined')
err = err.message;
alert("Error : " + err);
}
function log(message)
{
if (isIOS)
console.log(message);
else
console.info(message);
}
function onDeviceReady()
{
}
</script>
Pitch detection and manipulation (Autotune is a brand-name for a product Anteres Audio Technology that achieves it) is a hard digital signal processing problem (DSP) which is computationally intensive.
DPS Dimension provides a good tutorial here are about pitch manipulation, but it's very far from being a complete solution.
You are unlikely to make much headway with it without a strong academic background in DSP. Existing implementations are proprietary and typically implemented in C++. There are many patents in this problem space too.
One option might be to implement the audio processing server-side using a licensed component.
You might have more luck implementing a Vocoder in Javascript - the complexity is lower and there are plenty of algorithms in the public domain to try.
Related
I am using cordova push notification plugin un my angular application. I have created this service for the notifications:
define(["app"], function (app) {
'use strict';
var pushNotificationService = function ($q, localStorageService) {
var registrationDefered;
function registrationSuccess(result) {
}
function registrationError(error) {
}
function test(notificationData) {
localStorageService.set('notification_url', notificationData.url);
}
function isOnBrowser() {
var result = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
return !result;
}
//Android Amazon callback
app.onNotificationGCM = function(e) {
console.log(e);
switch(e.event) {
case 'registered':
if (e.regid.length > 0) {
// Your GCM push server needs to know the regID before it can push to this device
// here is where you might want to send it the regID for later use.
var data = {
registrationID: e.regid,
device: device.platform.toLocaleLowerCase()
};
registrationDefered.resolve(data);
}
break;
case 'message':
test(e.payload);
// if this flag is set, this notification happened while we were in the foreground.
// you might want to play a sound to get the user's attention, throw up a dialog, etc.
if (e.foreground) {
console.log(e);
// on Android soundname is outside the payload.
// On Amazon FireOS all custom attributes are contained within payload
var soundfile = e.soundname || e.payload.sound;
// if the notification contains a soundname, play it.
var my_media = new Media("/android_asset/www/"+ soundfile);
my_media.play();
} else {
// otherwise we were launched because the user touched a notification in the notification tray.
if (e.coldstart) {
//$("#app-status-ul").append('<li>--COLDSTART NOTIFICATION--' + '</li>');
} else {
//$("#app-status-ul").append('<li>--BACKGROUND NOTIFICATION--' + '</li>');
}
}
break;
case 'error':
break;
default:
break;
}
};
//public
var serviceApi = {
register: function() {
var pushNotification = window.plugins.pushNotification;
registrationDefered = $q.defer();
debugger;
if(device.platform.toLocaleLowerCase() == 'android' || device.platform == "amazon-fireos") {
pushNotification.register(
registrationSuccess,
registrationError,
{
"senderID": "238062858076",
"ecb":"angular.module('App').onNotificationGCM"
}
);
} else if(isOnBrowser()) {
var data = {
registrationId: "",
device: "browser"
};
registrationDefered.resolve(data);
}
/* else if (device.platform == 'blackberry10'){
pushNotification.register(
registrationSuccess,
registrationError,
{
invokeTargetId : "replace_with_invoke_target_id",
appId: "replace_with_app_id",
ppgUrl:"replace_with_ppg_url", //remove for BES pushes
ecb: "pushNotificationHandler",
simChangeCallback: replace_with_simChange_callback,
pushTransportReadyCallback: replace_with_pushTransportReady_callback,
launchApplicationOnPush: true
});
} else {
pushNotification.register(
tokenHandler,
errorHandler,
{
"badge":"true",
"sound":"true",
"alert":"true",
"ecb":"onNotificationAPN"
});
}*/
return registrationDefered.promise;
}
};
//public
return {
register: serviceApi.register
}
};
return pushNotificationService;
});
Now, I am able to register (I am getting the registration ID) but when the device receives a notification it seems that the application not running the js logic written in the callback function under the message case: test(e.payload).
Note that I'm am receiving the notification butlocalStorageService.set('notification_url', notificationData.url); is never being set to the provided value.
Can you please help me to understand why it is not running? is it even suppose to run (if the application is not running - installed but not running)
The thing is that I made the registration only on login. Now I have added this line to my module run callback:
app.run(function() {
pushNotificationService.register().then(function(result) {
console.log(result); //this just for debugging
});
});
I'm using PhantomJS to log into a site an do something. The site used OAuth for logging in. Clicking on the "Login" button on the, takes you to the OAuth service. There you enter your credentials and clicking "Submit", you get redirected back to the original site. My script works fine but relies on timeouts which doesn't seem too robust.
How can I rewrite this code so that instead of using setTimeout, I can wait until the page is ready. I often see errors that the page isnt' ready and therefore jQuery isn't initialized.
I'm not too good with Javascript so an example would be helpful. This is what I've hacked together after a ton of Googling. Here's my code:
var page = require('webpage').create();
var system = require('system');
page.settings.resourceTimeout = 10000;
page.onResourceTimeout = function(e) {
console.log("Timed out loading resource " + e.url);
};
page.open('https://mysite.com/login', function(status) {
if (status !== 'success') {
console.log('Error opening url');
phantom.exit(1);
} else {
setTimeout(function() {
console.log('Successfully loaded page');
page.evaluate(function() {
$("#submit-field").click(); //Clicking the login button
});
console.log('Clicked login with OAuth button');
setTimeout(function() {
console.log('Addding the credentials');
page.evaluate(function() {
document.getElementById("username").value = 'user#example.com';
document.getElementById("password").value = 'P#ssw0rd';
document.getElementById("Login").click();
});
console.log('Clicked login button');
setTimeout(function() {
//Inject some jQuery into the page and invoke that here
console.log('Clicked the export button');
}, 15000);
}, 15000);
});
}
});
It seems that the only way to do this was to use callbacks from the DOM to PhantomJS.
var page = require('webpage').create();
var system = require('system');
page.onInitialized = function() {
page.onCallback = function(data) {
console.log('Main page is loaded and ready');
//Do whatever here
};
page.evaluate(function() {
document.addEventListener('DOMContentLoaded', function() {
window.callPhantom();
}, false);
console.log("Added listener to wait for page ready");
});
};
page.open('https://www.google.com', function(status) {});
An alternate method would be to extend the phantomjs waitfor.js example.
I use this personnal blend of method.
This is my main.js file:
'use strict';
var wasSuccessful = phantom.injectJs('./lib/waitFor.js');
var page = require('webpage').create();
page.open('http://foo.com', function(status) {
if (status === 'success') {
page.includeJs('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', function() {
waitFor(function() {
return page.evaluate(function() {
if ('complete' === document.readyState) {
return true;
}
return false;
});
}, function() {
var fooText = page.evaluate(function() {
return $('#foo').text();
});
phantom.exit();
});
});
} else {
console.log('error');
phantom.exit(1);
}
});
And the lib/waitFor.js file (which is just a copy and paste of the waifFor() function from the phantomjs waitfor.js example):
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
// console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condi>
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
}
This method is not asynchronous but at least am I assured that all the resources were loaded before I try using them.
I'm building on top of an existing chrome extension, and I'm trying to maintain a consistent style. I need add a new feature, and I use the following script to save a user's choice from the popup selection, and then set a new popup going forward based on the saved choice.
userchoices.js:
require.scopes["userchoices"] = (function() {
var exports = {};
var userChoices = exports.userChoices = {
userchoices: {},
updateChoice: function(){
self = this;
chrome.storage.local.get('userchoices', function(items){
if(!items.userchoices){
chrome.storage.local.set({userchoices: self.userchoices});
return;
}
self.userchoices = items.userchoices;
});
},
getChoice: function(url){
if(this.userchoices[url]){
return this.userchoices[url][choice];
} else {
return {};
}
},
setChoice: function(url, newChoice){
if(!this.userchoices[url]){
this.userchoices[url] = {};
}
this.userchoices[url][choice] = newChoice;
chrome.storage.local.set({userchoices: this.userchoices});
},
removeChoice: function(url){
if(!this.userchoices[url]){
return;
} else {
delete this.userchoices[url]
}
chrome.storage.local.set({userchoices: this.userchoices});
}
}
return exports;
})();
background.js:
var userChoices= require("userchoices").userChoices;
chrome.windows.onCreated.addListener(function(){
CookieBlockList.updateDomains();
BlockedDomainList.updateDomains();
FakeCookieStore.updateCookies();
userChoices.updateChoice();
});
function refreshIconAndContextMenu(tab)
{
// The tab could have been closed by the time this function is called
if(!tab)
return;
var choice = userChoices.getChoice(tab.url);
if(choice) {
if (choice == "one"){
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupDontCare.html"});
} else if(choice=="two"){
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupSortofCare.html"});
} else if(choice=="three") {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupCare.html"});
} else if(choice=="four") {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popupReallyCare.html"});
} else {
chrome.browserAction.setPopup({tabId: tab.id, popup: "skin/popup.html"});
}}
}
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "loading")
refreshIconAndContextMenu(tab);
});
// Update icon if a tab is replaced or loaded from cache
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId){
chrome.tabs.get(addedTabId, function(tab){
refreshIconAndContextMenu(tab);
});
});
popup.js:
var userChoices = require("userchoices").userChoices;
function init()
{
console.log("Initializing popup.js");
// Attach event listeners
$("#Dont_Care_btn").click(doNothing);
$("#Sort_of_Care_btn").click(doBadger);
$("#Care_btn").click(giveSecrecyBadger);
$("#Really_Care_btn").click(giveAdvice);
$("#Nuance_btn").click(addNuance);
}
function doNothing() {
$("#startingQuestion").hide();
$("#DontCareResponse").show();
$("#siteControls").hide();
userChoices.setChoice(tab.url, "one");
refreshIconAndContextMenu(tab);
}
function doBadger() {
$("#startingQuestion").hide();
$("#SortofCareResponse").show();
$("#siteControls").hide();
$("#blockedResourcesContainer").hide();
$("#Nuance_btn").show();
userChoices.setChoice(tab.url, "two");
refreshIconAndContextMenu(tab);
}
function giveSecrecyBadger() {
$("#startingQuestion").hide();
$("#siteControls").hide();
$("#CareResponse").show();
$("#siteControls").hide();
$("#blockedResourcesContainer").hide();
$("#Nuance_btn").show();
userChoices.setChoice(tab.url, "three");
refreshIconAndContextMenu(tab);
}
function giveAdvice() {
$("#startingQuestion").hide();
$("#siteControls").hide();
$("#ReallyCareResponse").show();
userChoices.setChoice(tab.url, "four");
refreshIconAndContextMenu(tab);
}
The popup is currently not being set, and I'm not even sure that the selection is saved successfully. Anyone see a problem?
Ha! In the middle of trying to create a minimal example, I figured out the problem. Turns out the problem was the now-deprecated chrome.tabs.getSelected method when it should have been chrome.tabs.query()
Thanks Xan!
I have the following code to listen firefox quit-application event
observe: function(subject, topic, data)
{
if (topic == "profile-after-change" || topic == "app-startup") {
var os = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
// add observer for https response tracking
os.addObserver(this, "http-on-modify-request", false);
os.addObserver(this, "http-on-examine-response", false);
os.addObserver(this, "http-on-examine-cached-response", false);
os.addObserver(this, "quit-application", false);
}
else if (topic == "quit-application")
{
LOG("inside quit-application Testing ");
var os = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "quit-application");
var appInfo = Components.classes["#mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var tempappVersion = appInfo.version;
var appVersion = tempappVersion.split(".");
if(appVersion[0] >= 4)
{
setAddonEnableListener();
}
return;
}
}
function setAddonEnableListener()
{
try {
LOG("inside setAddonEnableListener method ");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("myextension#extension.com", function(addon)
{
if (addon.userDisabled)
addon.userDisabled = false;
});
} catch (ex) {
}
}
This code is supposed to re enable the disabled addon after firefox restart happens,but this is not at all working.I am not able to debug the code after firefox quits as the error console is clearing its log.So,I could not conclude whether the quit-application is fired or problem with my "setAddonEnableListener" to enable the addon.
Please give me any suggestions what I am doing wrong.
I have found the problem is with setAddonEnableListener() method,just as a try I have replaced
if (topic == "quit-application")
{
LOG("inside quit-application Testing ");
var os = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "quit-application");
var appInfo = Components.classes["#mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var tempappVersion = appInfo.version;
var appVersion = tempappVersion.split(".");
if(appVersion[0] >= 4)
{
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("myextension#extension.com", function(addon)
{
if (addon.userDisabled)
addon.userDisabled = false;
});
} catch (ex) {
}
}
With this I am able to reenable my addon.
var inDoubleTap = false; // Shared across all bound elements
return $list.live('touchstart', function(e) {
if (e.originalEvent.touches.length === 1) {
if (!inDoubleTap) {
inDoubleTap = true;
setTimeout(function() { inDoubleTap = false }, delay);
} else {
inDoubleTap = false;
callback.call(this, e);
exit(0);
}
}
});
The above code shows an error if i use exit(0) in mobile browsers (iphone, ipad)
Surely you mean return; instead of exit(0). That should work.