Docs¶
-
class
reem.datatypes.
Writer
(top_key_name, interface)¶ Responsible for setting data inside Redis
The Writer class is an internal class that is used for all data sent to Redis (not including pub/sub messages). Each key that will have nested data below requires a new instantiation of Writer
-
top_key_name
¶ The name of the Redis key under which JSON data will be stored. To Redis, this will become a ReJSON key name. It is also used to generate the Redis key name that
ship
’s use to store non JSON data.- Type
str
-
interface
¶ Defines the connection to Redis this writer will use
- Type
RedisInterface
-
send_to_redis
(set_path, set_value)¶ Execute equivalent of
JSON.SET self.top_key_name <set_path> <set_value>
From the user’s perspective, it executes
JSON.SET self.top_key_name <set_path> <set_value>
except thatset_value
can be json-incompatible. This is the only public method of this class. It determines what non-serializable types are inside set_value, stores the serializable data as a JSON, and stores the non-serializable data usingself.interface
’s ships- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
-
_Writer__initialize_metadata
()¶ Pull metadata for this key from Redis or set a default
- Returns
None
-
_Writer__process_metadata
(set_path, set_value)¶ Handle metadata updates
Given the path and value the user would like to set, check if there are non-serializable data types and update metadata locally and in Redis. Happens without pipeline
- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
-
_Writer__publish_non_serializables
(set_path, set_value)¶ Publish JSON incompatible data to Redis
Given a set, publish the non-serializable components to redis, given that metadata has been updated already
- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
-
-
class
reem.datatypes.
Reader
(top_key_name, interface)¶ Responsible for getting data from Redis
The Reader class is an internal class that is used for all read from Redis (not including pub/sub messages). Each key that will have nested data below requires a new instantiation of Reader
-
top_key_name
¶ The name of the Redis key under which JSON data is stored
- Type
str
-
interface
¶ Defines the connection to Redis this reader will use
- Type
RedisInterface
-
read_from_redis
(read_path)¶ Read specified path from Redis
This is the only public method of the Reader class. It will retrieve the data stored at a specified path from Redis. At a high level, it reads data stored with ReJSON and inserts non-JSON compatible data at appropriate paths using the metadata associated with this key.
- Parameters
read_path (str) – path the user wants to read
Returns: data stored at value in Redis
-
update_metadata
()¶ Update the local copy of metadata if a relevant path has been updated.
The metadata listener is a redis client subscribed to key-space notifications. If a relevant path is updated, this Reader’s
pull_metadata
flag will be turned on. Ifpull_metadata
isTrue
, then the reader will fetch metadata from the Redis server.Returns: None
-
queue_reads
(read_path)¶ Queue reads in a pipeline
Queue all redis queries necessary to read data at path into the appropriate redis pipeline. First, queue decoded pipeline with the ReJSON query Next, queue all the special path reads with the non-decoded pipeline and ships
- Parameters
read_path – path user wants to read
Returns: None
-
build_dictionary
(read_path)¶ Execute pipelines and consolidate data into a dictionary
- Parameters
read_path – path user wants to read
Returns: The data stored at
read_path
in Redis
-
pull_special_path
(read_path)¶ Directly pull a non-JSON path
If the user specified path is not in JSON, this will retrieve the data directly without going through ReJSON.
- Parameters
read_path – path user wants to read
Returns:
-
-
class
reem.datatypes.
KeyValueStore
(interface)¶ Dictionary Like object used for get/set paradigm
The
KeyValueStore
object is one that users will frequently use. It keepsReader
andWriter
objects for each key that the user read or written to. It does not actually handle the getting and setting of data but producesReadablePathHandler
objects that assist with path construction and call the reader and writer’s write and read methods.-
interface
¶ Defines the connection to Redis this reader will use
- Type
RedisInterface
-
track_schema_changes
(set_value, keys=None)¶ Performance optimization for skipping schema update checks
Stop checking for schema updates when setting data. Use ONLY if your data’s schema is static and you are really trying to eek out every bit of optimization.
- Parameters
set_value (bool) – True/False indicating if the keys’ schema should be tracked
keys (List[str]) – List of keys to track. If None, all present and future keys are tracked
to set_value (according) –
Returns: None
-
_KeyValueStore__ensure_key_existence
(key)¶ Ensure that the requested key has a reader and writer associated with it.
Returns: None
-
-
class
reem.datatypes.
Publisher
(top_key_name, interface)¶ Defines Publisher behavior
The Publisher is identical to the writer but publishes a message when it writes a value.
-
send_to_redis
(set_path, set_value)¶ Publisher equivalent of Writer
send_to_redis
This is an equivalent function to
Writer
’ssend_to_redis
method but also publishes a message indicating what channel has been updated.- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
Returns: None
-
_Writer__initialize_metadata
()¶ Pull metadata for this key from Redis or set a default
- Returns
None
-
_Writer__process_metadata
(set_path, set_value)¶ Handle metadata updates
Given the path and value the user would like to set, check if there are non-serializable data types and update metadata locally and in Redis. Happens without pipeline
- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
-
_Writer__publish_non_serializables
(set_path, set_value)¶ Publish JSON incompatible data to Redis
Given a set, publish the non-serializable components to redis, given that metadata has been updated already
- Parameters
set_path (str) – path underneath JSON key to set
set_value – value to set
- Returns
None
-
-
class
reem.datatypes.
PublishSpace
(interface)¶ Convenience class for publishing
This class keeps track of
Publisher
objects for each key the user has published on.-
_KeyValueStore__ensure_key_existence
(key)¶ Ensure that the requested key has a reader and writer associated with it.
Returns: None
-
_PublishSpace__ensure_key_existence
(key)¶ Identical to
KeyValueStore
method of same name but does not instantiate aReader
object
-
track_schema_changes
(set_value, keys=None)¶ Performance optimization for skipping schema update checks
Stop checking for schema updates when setting data. Use ONLY if your data’s schema is static and you are really trying to eek out every bit of optimization.
- Parameters
set_value (bool) – True/False indicating if the keys’ schema should be tracked
keys (List[str]) – List of keys to track. If None, all present and future keys are tracked
to set_value (according) –
Returns: None
-
-
class
reem.datatypes.
SilentSubscriber
(channel, interface)¶ Silent Subscriber Implementation
-
update_local_copy
(channel, message)¶ Update the local copy of the data stored under this channel name in redis.
- Parameters
channel – the name of the channel that was published.
message – message published on that channel
Returns: None
-
listen
()¶ Makes this subscriber start listening
Returns: None
-
value
()¶ Get data stored at root
Where as the reader can do
server["foo"].read()
with if server is aKeyValueStore
, accessing the root value of a subscriber is not as easy. This method retrieves all data stored underneath a top level key.Returns: all data stored underneath a top level Redis key.
-
build_dictionary
(read_path)¶ Execute pipelines and consolidate data into a dictionary
- Parameters
read_path – path user wants to read
Returns: The data stored at
read_path
in Redis
-
pull_special_path
(read_path)¶ Directly pull a non-JSON path
If the user specified path is not in JSON, this will retrieve the data directly without going through ReJSON.
- Parameters
read_path – path user wants to read
Returns:
-
queue_reads
(read_path)¶ Queue reads in a pipeline
Queue all redis queries necessary to read data at path into the appropriate redis pipeline. First, queue decoded pipeline with the ReJSON query Next, queue all the special path reads with the non-decoded pipeline and ships
- Parameters
read_path – path user wants to read
Returns: None
-
read_from_redis
(read_path)¶ Read specified path from Redis
This is the only public method of the Reader class. It will retrieve the data stored at a specified path from Redis. At a high level, it reads data stored with ReJSON and inserts non-JSON compatible data at appropriate paths using the metadata associated with this key.
- Parameters
read_path (str) – path the user wants to read
Returns: data stored at value in Redis
-
update_metadata
()¶ Update the local copy of metadata if a relevant path has been updated.
The metadata listener is a redis client subscribed to key-space notifications. If a relevant path is updated, this Reader’s
pull_metadata
flag will be turned on. Ifpull_metadata
isTrue
, then the reader will fetch metadata from the Redis server.Returns: None
-
-
class
reem.datatypes.
CallbackSubscriber
(channel, interface, callback_function, kwargs)¶ Callback Subscriber Implementation
-
call_user_function
(channel, message)¶ Wrapper callback function (wrapping user function) for this class to work with a RawSubscriber object Fits required interface for a ChannelSubscriber callback function :param channel: channel published to :param message: message that was published :return: None :rtype: None
-
build_dictionary
(read_path)¶ Execute pipelines and consolidate data into a dictionary
- Parameters
read_path – path user wants to read
Returns: The data stored at
read_path
in Redis
-
listen
()¶ Makes this subscriber start listening
Returns: None
-
pull_special_path
(read_path)¶ Directly pull a non-JSON path
If the user specified path is not in JSON, this will retrieve the data directly without going through ReJSON.
- Parameters
read_path – path user wants to read
Returns:
-
queue_reads
(read_path)¶ Queue reads in a pipeline
Queue all redis queries necessary to read data at path into the appropriate redis pipeline. First, queue decoded pipeline with the ReJSON query Next, queue all the special path reads with the non-decoded pipeline and ships
- Parameters
read_path – path user wants to read
Returns: None
-
read_from_redis
(read_path)¶ Read specified path from Redis
This is the only public method of the Reader class. It will retrieve the data stored at a specified path from Redis. At a high level, it reads data stored with ReJSON and inserts non-JSON compatible data at appropriate paths using the metadata associated with this key.
- Parameters
read_path (str) – path the user wants to read
Returns: data stored at value in Redis
-
update_local_copy
(channel, message)¶ Update the local copy of the data stored under this channel name in redis.
- Parameters
channel – the name of the channel that was published.
message – message published on that channel
Returns: None
-
update_metadata
()¶ Update the local copy of metadata if a relevant path has been updated.
The metadata listener is a redis client subscribed to key-space notifications. If a relevant path is updated, this Reader’s
pull_metadata
flag will be turned on. Ifpull_metadata
isTrue
, then the reader will fetch metadata from the Redis server.Returns: None
-
value
()¶ Get data stored at root
Where as the reader can do
server["foo"].read()
with if server is aKeyValueStore
, accessing the root value of a subscriber is not as easy. This method retrieves all data stored underneath a top level key.Returns: all data stored underneath a top level Redis key.
-


--- title: Intro to Dataviz ⟩ Spring 2022 courseno: W4995.011 forms: submit: https://forms.gle/P1uvVsXe5wc6HA9h9 peer: https://forms.gle/V8LKGR85GjtxCxzHA apply: https://forms.gle/WiVrXP2MjSwXGRmW8 feedback: https://forms.gle/58Ep91Y5wxRwH7Sg9 courseworks: https://courseworks2.columbia.edu/courses/151105 canvasfiles: https://courseworks2.columbia.edu/courses/151105/files/ ---
{% if page.title %}


"x"
"1" "LYNN,RK, GARVIE-GOULD,C, WONG,K AND KENNISH,JM, METABOLISM,DISTRIBUTION, AND EXCRETION OF THE FLAME RETARDANT,TRIS(2,3-DIBROMOPROPYL)PHOSPHATE (TRIS-BP) IN THE RAT: IDENTIFICATION OFMUTAGENIC AND NEPH __ ROTOXIC METABOLITES, TOXICOL. APPL. PHARMACOL. 63:105-119,1982"


-->
20/10/1911
Framheim
24/10/1911
Depot 1
31/10/1911
Depot 2
01/11/1911
Steershead Crevasses
07/11/1911
Depot 3
08/11/1911
Discovery
09/11/1911
83°S
17/11/1911
Betty's Knoll
18/11/1911
Axel Heiberg Glacier
19/11/1911
Axel Heiberg Glacier
20/11/1911
Axel Heiberg Glacier ice falls
21/11/1911
Butcher's Shop
26/11/1911
Plateau journey begins
28/11/1911
Devil's Glacier
04/12/1911
Devil's dance floor
08/11/1911
Passed Shackleton's Farthest South
15/12/1911
The Pole


ScribeUI
v0.2
Manager
Editor
Browse
Name
Password
Maps
New Map
Open Map
Export Map
Delete Map
New Group
Group Settings
Map
Scales
Symbols
Fonts
Projections
Open Logs
Logs
Debug
Result
Close
Go!
+
Save
Name
Password
Name
Type
Workspace
Password
Template
Description
Public data
Private data
Preparing data...
Name
Name
Map
Extent
Current Extent
Set Extent


Head Blacksmith Noel:
Didn't I tell you? Caradine was urgently looking for you.


--- layout: post title: Phone date: '2014-12-22T07:30:40+01:00' categories: - Illustration - Sketches picture_url: https://film-Storyboards.tumblr.com/post/105866532333/concept-Sketches ---
Concept Sketches.


The jQuery project started as an inkling back in 2005 and has grown into the collection of projects that we know today.
2012
August
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
July
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
2011
August
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project
July
-
August 13th, 2010 - The jQuery Project is to Announce jQuery Mobile Project


Though medications may be the single most important healthcare intervention for chronic disease in the developed world (1,2), their impact is modulated by patient adherence. Even for conditions where using a single medication only once a day is known to improve outcomes, only about 50% of patients adhere to the correct regimen (3-5). Studies of patients taking antihypertensives, antidepressives, antidiabetics, antipsychotics and antihyperlipidemics show that poor adherence is predictive of poor outcomes and high costs, including future hospitalizations and treatment discontinuation (8-20). Conversely, consistent adherence to statins, antihypertensives, antidiabetic agents and antiviral therapies is associated with positive health outcomes (3,18,19,21).
Causes of non-adherence are multifactorial, including tolerability, side effects, complexity of prescribing and filling procedures, level of understanding of the importance of taking the medication, cultural norms, out of pocket cost of the medication and the possible lack of discernable effects of the medication (1,22-25). The effort to intervene effectively by healthcare providers is hampered by a tendency to overestimate medication adherence (26-31).
Surveillance of adherence can be achieved monitoring records of dispensed prescription medications (6,7). Prescription filling data provides an indirect measure of adherence to prescription medication. Although filled prescription medications are not always taken, it is generally true that patients who do not fill a prescription are non-adherent. We sought to develop a model of prescription fill data for early identification of patients prescribed antihyperlipidemics, antihypertensives and oral hypoglycemics who will likely be poor adherers one year after the start of a prescription.
The large-gap detection system was set to flag drug eras that accumulated a continuous medication gap greater than 30 days, based on the assumption that a patient lacking a months worth of medication supply could benefit from the attention of a clinician. Of the remaining unflagged subjects who consistently filled prescriptions over the course of at least one year, we focused on identifying those at high risk of future poor adherence, so that an intervention could be made early in the course of their drug therapy. Our two-phase detector identifies subjects at high risk of poor adherence to chronic medications as early as 60 days after the first prescription fill.
This study is a retrospectively constructed two-phase prediction model for early identification of patients at risk of poor adherence to chronic medications. The first phase is a straightforward approach to identifying prolonged gaps in prescription filling patterns. The second phase uses a regression model to isolate more complex and subtly patterns predictive of future poor adherence.


Refresh
Now Playing
Billy The Auto DJ
Song
Artist
Album
{{ song.Track }}
{{ song.Artist }}
{{ song.Album }}


Perhaps the easiest way to find your next favorite color.
Press the spacebar or tap to create a new color. The back key will take you through your color history. The forward key will go the other way.
Built by Chris Schnaars. Find the code on Github.


IBM
Watson
Assistant Solutions
Get Support
Edit This Page
{{ content }}
{% include partials/sidebar.html %}
{% if jekyll.environment != 'production' %} {% endif %}


Masterpass is a digital wallet that allows consumers to pay with any payment card, on a website or app, with any device.


application has been started.
Checking for newer version...
There are no newer version avaliable.
A newer version has been found.
version:
release notes:
click herer to update your dorame to lastest version
or here to continue current version
version:
release notes:
click herer to update your dorame to lastest version
or here to continue current version
updating progress:0%
error occured when msg ( ).
continue
continue
update complete


q, k, v = qkv
B, H, T, _ = q.shape
q = q.zero_()
res, _ = attn(q, k, v)
res = res.numpy()
gold = v.numpy()
for b in range(B):
for h in range(H):
q, k, v = qkv
B, H, T, _ = q.shape
q = q.zero_()
res = attn((q, k, v, None))
res = res.numpy()
gold = v.numpy()
for b in range(B):
for h in range(H):


There are three different classes of objects which together constitute the document control. These are
GenDocumentControlClass
,
GenDocumentGroupClass
, and
GenDocumentClass
. A document will need at least one of each to use the document control technology. The relationship between the objects is diagramed below.
An application will have one object of class
GenDocumentControlClass
. This object manages the user interface: It presents some dialog and alert boxes, it manages the File Selector, it creates appropriate entries for the File menu, and it updates the enabled/disabled states of these items (e.g. it disables the
Save
trigger after the file has been saved).
The GenDocumentControl is generally made a child of the file menu, which is itself a child (or descendant) of the GenPrimary. The GenDocumentControl is on the GenPrimary's active list. It has no children, but it does have an optr to the GenDocumentGroup object. By convention, the GenDocumentControl object is in the same data segment as the GenPrimary object. Certain attributes of the GenDocumentControl object will determine the characteristics of the File Selector and other UI gadgets.
GenDocumentControlClass
is a subclass of
GenControlClass
. This means that you can set up toolboxes to perform the "Save," "Open," etc., actions. For more details, see the Controllers chapter.
An application will have one object of class
GenDocumentGroupClass
. This object creates and manages the document objects. Ordinarily, the document objects belong to
GenDocumentClass
. However, if the program wishes to alter the behavior of the document object, it can create a subclass of
GenDocumentClass
. In this case, the GenDocumentGroup object will contain a pointer to the class definition of the document subclass, and will create document objects of this class as needed.
The GenDocumentGroup object is a child of any object. It does not have any children when it is declared; however, it will dynamically give itself document-object children at run-time. It is in its own data segment. Certain of its attributes determine what the attributes of its document children will be.
Each GenDocument object manages a single open file. It keeps track of the volume, path, and filename for the document, the dirty state of the document, and other document-related information. It opens and closes files and presents file-related dialog boxes (e.g., "Save changes before closing?"). Programs often define a subclass of the
GenDocumentClass
which has additional, application-related functionality. In this case, objects of the subclass are used instead of objects of
GenDocumentClass
.
GenDocumentClass
is a subclass of
GenContentClass
. Therefore, document objects can receive the output of GenView objects. GenDocument objects have all the functionality of GenContent objects. GenContent objects are themselves subclassed from
GenClass
. Very few applications will use the GenContent objects directly; for that reason, they are documented in this chapter.
Document objects are not declared in the source code; they are created at run-time by the GenDocumentGroup object. The document currently active is called the target document .


product-info: < |
product and Suite name info.
- product-name - string
- suite-name - string
- search - boolea, if has search.
|
The Product and suite name info, also include if search exist or not, like: productInfo = {
product-name: "WebUI Look & Feel",
suite-name: "(WULF)",
search: true
};
|
utility-set: < |
utility controls info array include following items:.
- type - string, links or menu
- name - string, name
- link - string, url.
- menuItems - string array for menu type, null for links type.
|
The Utility controls info data like: utility-set= [
{
type: "links",
name: "User Name",
link: "#",
menuItems: [],
disable: false
}]
|
nav-tabs-info: < |
navigation control info:
navTabIndex- active tab index; navigation Tab item array info which include:
- label - string, links or menu
- css-class - string, name
- link - string, url.
- data-item - string, associated nav tab item and tab content
- menu-bar - string array for menu/sub menu items, only display for cssClass type of dropdown.
|
nav-tabs-info ={
navTabIndex: -1,
navTabs: [
{
label: "item 1",
cssClass: "n-banner-3Link",
link: "#",
dataItem: "item1",
menuBar: ""
}]
|
action-set: < |
action controls info array include following items:.
- name - string, links or menu
- css-class - "dropdown" or empty string, just one Action ,you can use empty string
- icon - string, name
- link - string, url.
- has-child - string array for menu type, null for links type.
- childItems - string, url.
|
action-set = [
{
name: "Manage",
cssClass: "dropdown",
icon: "icon icon-manage",
link: "#",
hasChild: true,
childItems: [
{name: "sub item1", link: "#",selected: false},
{name: "sub item2", link: "#",selected: false}
]
},
|
overflow-open: < |
|
overflow-open = true; if "overflowOpen = true",overflow function will open ,vice versa.
|


Soundchip: Z80 Variant
Properties of the System
Note Range: C-1 -> C-8
Max Volume: F on SQ1/SQ2/Noise Channel, 3 on WAVE Channel.


please select 1
please select 2
please select 3
age ASC
age desc
select bg1
select bg2
select bg3
Name
Age
{{answer.name}}
{{answer.age}}


{% extends "tutorial.html" %} {% block headauthor %}Boris Smus{% endblock %} {% block headtitle %}Getting Started with Web Audio API{% endblock %} {% block pagetitle %}Getting Started with Web Audio API{% endblock %} {% block pagebreadcrumb %}Getting Started with Web Audio API{% endblock %} {% block date %}October 14, 2011{% endblock %} {% block head %} {% endblock %} {% block browsersupport %} Operaunsupported Internet Explorerunsupported Safarisupported Firefoxunsupported Chromesupported {% endblock %} {% block iscompatible %} return !!(window.AudioContext || window.webkitAudioContext); {% endblock %} {% block html5badge %} {% endblock %} {% block content %}
Before the HTML5 <audio>
element, Flash or another plugin was required
to break the silence of the web. While audio on the web no longer
requires a plugin, the audio tag brings significant limitations for
implementing sophisticated games and interactive applications.
The Web Audio API is a high-level JavaScript API for processing and synthesizing audio in web applications. The goal of this API is to include capabilities found in modern game audio engines and some of the mixing, processing, and filtering tasks that are found in modern desktop audio production applications. What follows is a gentle introduction to using this powerful API.
An AudioContext is for managing and playing all sounds. To produce
a sound using the Web Audio API, create one or more sound sources
and connect them to the sound destination provided by the AudioContext
instance. This connection doesn't need to be direct, and can go through
any number of intermediate AudioNodes which act as processing
modules for the audio signal. This routing is described in greater
detail at the Web Audio specification.
A single instance of AudioContext
can support multiple sound inputs
and complex audio graphs, so we will only need one of these for each
audio application we create. Many of the interesting Web Audio API functions such as creating
AudioNodes and decoding audio file data are methods of AudioContext
.
The following snippet creates an AudioContext
:
var context;
window.addEventListener('load', init, false);
function init() {
try {
// Fix up for prefixing
window.AudioContext = window.AudioContext||window.webkitAudioContext;
context = new AudioContext();
}
catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
For WebKit- and Blink-based browsers, you currently need to use the webkit
prefix, i.e.
webkitAudioContext
.
The Web Audio API uses an AudioBuffer for short- to medium-length sounds. The basic approach is to use XMLHttpRequest for fetching sound files.
The API supports loading audio file data in multiple formats, such as WAV, MP3, AAC, OGG and others. Browser support for different audio formats varies.
The following snippet demonstrates loading a sound sample:
var dogBarkingBuffer = null;
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function loadDogSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
}
The audio file data is binary (not text), so we set the responseType
of the request to 'arraybuffer'
. For more information about
ArrayBuffers
, see this article about XHR2.
Once the (undecoded) audio file data has been received, it can be kept
around for later decoding, or it can be decoded right away using the
AudioContext decodeAudioData()
method. This method takes the
ArrayBuffer
of audio file data stored in request.response
and
decodes it asynchronously (not blocking the main JavaScript execution
thread).
When decodeAudioData()
is finished, it calls a callback function which
provides the decoded PCM audio data as an AudioBuffer
.
Once one or more AudioBuffers
are loaded, then we're ready to play
sounds. Let's assume we've just loaded an AudioBuffer
with the sound
of a dog barking and that the loading has finished. Then we can play
this buffer with the following code.
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.start(0); // play the source now
// note: on older systems, may have to use deprecated noteOn(time);
}
This playSound()
function could be called every time somebody presses a key or
clicks something with the mouse.
The start(time)
function makes it easy to schedule precise sound
playback for games and other time-critical applications. However, to get
this scheduling working properly, ensure that your sound buffers are
pre-loaded. (On older systems, you may need to call noteOn(time)
instead of start(time)
.)
An important point to note is that on iOS, Apple currently mutes all sound output until the first time a sound is played during a user interaction event - for example, calling playSound()
inside a touch event handler. You may struggle with Web Audio on iOS "not working" unless you circumvent this - in order to avoid problems like this, just play a sound (it can even be muted by connecting to a Gain Node with zero gain) inside an early UI event - e.g. "touch here to play".
Of course, it would be better to create a more general loading system which isn't hard-coded to loading this specific sound. There are many approaches for dealing with the many short- to medium-length sounds that an audio application or game would use–here's one way using a BufferLoader class.
The following is an example of how you can use the BufferLoader
class.
Let's create two AudioBuffers
; and, as soon as they are loaded,
let's play them back at the same time.
window.onload = init;
var context;
var bufferLoader;
function init() {
// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
bufferLoader = new BufferLoader(
context,
[
'../sounds/hyper-reality/br-jam-loop.wav',
'../sounds/hyper-reality/laughter.wav',
],
finishedLoading
);
bufferLoader.load();
}
function finishedLoading(bufferList) {
// Create two sources and play them both together.
var source1 = context.createBufferSource();
var source2 = context.createBufferSource();
source1.buffer = bufferList[0];
source2.buffer = bufferList[1];
source1.connect(context.destination);
source2.connect(context.destination);
source1.start(0);
source2.start(0);
}
The Web Audio API lets developers precisely schedule playback. To demonstrate this, let's set up a simple rhythm track. Probably the most widely known drumkit pattern is the following:
in which a hihat is played every eighth note, and kick and snare are played alternating every quarter, in 4/4 time.
Supposing we have loaded the kick
, snare
and hihat
buffers, the
code to do this is simple:
for (var bar = 0; bar < 2; bar++) {
var time = startTime + bar * 8 * eighthNoteTime;
// Play the bass (kick) drum on beats 1, 5
playSound(kick, time);
playSound(kick, time + 4 * eighthNoteTime);
// Play the snare drum on beats 3, 7
playSound(snare, time + 2 * eighthNoteTime);
playSound(snare, time + 6 * eighthNoteTime);
// Play the hi-hat every eighth note.
for (var i = 0; i < 8; ++i) {
playSound(hihat, time + i * eighthNoteTime);
}
}
Here, we make only one repeat instead of the unlimited loop we see in
the sheet music. The function playSound
is a method that plays a
buffer at a specified time, as follows:
function playSound(buffer, time) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(time);
}
One of the most basic operations you might want to do to a sound is change its volume. Using the Web Audio API, we can route our source to its destination through an GainNode in order to manipulate the volume:
This connection setup can be achieved as follows:
// Create a gain node.
var gainNode = context.createGain();
// Connect the source to the gain node.
source.connect(gainNode);
// Connect the gain node to the destination.
gainNode.connect(context.destination);
After the graph has been set up, you can programmatically change the
volume by manipulating the gainNode.gain.value
as follows:
// Reduce the volume.
gainNode.gain.value = 0.5;
The following is a demo of a volume control implemented with an <input
type="range">
element:
Volume:
Now, suppose we have a slightly more complex scenario, where we're playing multiple sounds but want to cross fade between them. This is a common case in a DJ-like application, where we have two turntables and want to be able to pan from one sound source to another.
This can be done with the following audio graph:
To set this up, we simply create two GainNodes, and connect each source through the nodes, using something like this function:
function createSource(buffer) {
var source = context.createBufferSource();
// Create a gain node.
var gainNode = context.createGain();
source.buffer = buffer;
// Turn on looping.
source.loop = true;
// Connect source to gain.
source.connect(gainNode);
// Connect gain to destination.
gainNode.connect(context.destination);
return {
source: source,
gainNode: gainNode
};
}
A naive linear crossfade approach exhibits a volume dip as you pan between the samples.
To address this issue, we use an equal power curve, in which the corresponding gain curves are non-linear, and intersect at a higher amplitude. This minimizes volume dips between audio regions, resulting in a more even crossfade between regions that might be slightly different in level.
The following demo uses an <input type="range">
control to crossfade
between the two sound sources:
Drums Organ
Another common crossfader application is for a music player application.
When a song changes, we want to fade the current track out, and fade the
new one in, to avoid a jarring transition. To do this, schedule a
crossfade into the future. While we could use setTimeout
to do this
scheduling, this is not precise. With the Web Audio API, we
can use the AudioParam interface to schedule future values for
parameters such as the gain value of an GainNode
.
Thus, given a playlist, we can transition between tracks by scheduling a gain decrease on the currently playing track, and a gain increase on the next one, both slightly before the current track finishes playing:
function playHelper(bufferNow, bufferLater) {
var playNow = createSource(bufferNow);
var source = playNow.source;
var gainNode = playNow.gainNode;
var duration = bufferNow.duration;
var currTime = context.currentTime;
// Fade the playNow track in.
gainNode.gain.linearRampToValueAtTime(0, currTime);
gainNode.gain.linearRampToValueAtTime(1, currTime + ctx.FADE_TIME);
// Play the playNow track.
source.start(0);
// At the end of the track, fade it out.
gainNode.gain.linearRampToValueAtTime(1, currTime + duration-ctx.FADE_TIME);
gainNode.gain.linearRampToValueAtTime(0, currTime + duration);
// Schedule a recursive track change with the tracks swapped.
var recurse = arguments.callee;
ctx.timer = setTimeout(function() {
recurse(bufferLater, bufferNow);
}, (duration - ctx.FADE_TIME) * 1000);
}
The Web Audio API provides a convenient set of RampToValue
methods to
gradually change the value of a parameter, such as
linearRampToValueAtTime
and exponentialRampToValueAtTime
.
While the transition timing function can be picked from built-in linear
and exponential ones (as above), you can also specify your own value
curve via an array of values using the setValueCurveAtTime
function.
The following demo shows an playlist-like auto-crossfade between two tracks using the above approach:
The Web Audio API lets you pipe sound from one audio node into another, creating a potentially complex chain of processors to add complex effects to your soundforms.
One way to do this is to place BiquadFilterNodes between your sound source and destination. This type of audio node can do a variety of low-order filters which can be used to build graphic equalizers and even more complex effects, mostly to do with selecting which parts of the frequency spectrum of a sound to emphasize and which to subdue.
Supported types of filters include:
And all of the filters include parameters to specify some amount of gain, the frequency at which to apply the filter, and a quality factor. The low-pass filter keeps the lower frequency range, but discards high frequencies. The break-off point is determined by the frequency value, and the Q factor is unitless, and determines the shape of the graph. The gain only affects certain filters, such as the low-shelf and peaking filters, and not this low-pass filter.
Let's setup a simple low-pass filter to extract only the bases from a sound sample:
// Create the filter
var filter = context.createBiquadFilter();
// Create the audio graph.
source.connect(filter);
filter.connect(context.destination);
// Create and specify parameters for the low-pass filter.
filter.type = 'lowpass'; // Low-pass filter. See BiquadFilterNode docs
filter.frequency.value = 440; // Set cutoff to 440 HZ
// Playback the sound.
source.start(0);
The following demo uses a similar technique and lets you enable and disable a lowpass filter via a checkbox, as well as tweak the frequency and quality values with the slider:
Filter on: Frequency: Quality:
In general, frequency controls need to be tweaked to work on a
logarithmic scale since human hearing itself works on the same principle
(that is, A4 is 440hz, and A5 is 880hz). For more details, see the
FilterSample.changeFrequency
function in the source code link above.
Lastly, note that the sample code lets you connect and disconnect the
filter, dynamically changing the AudioContext graph. We can disconnect
AudioNodes from the graph by calling node.disconnect(outputNumber)
.
For example, to re-route the graph from going through a filter, to a
direct connection, we can do the following:
// Disconnect the source and filter.
source.disconnect(0);
filter.disconnect(0);
// Connect the source directly.
source.connect(context.destination);
We've covered the basics of the API, including loading and playing audio samples. We've built audio graphs with gain nodes and filters, and scheduled sounds and audio parameter tweaks to enable some common sound effects. At this point, you are ready to go and build some sweet web audio applications!
If you are seeking inspiration, many developers have already created great work using the Web Audio API. Some of my favorite include:


Constants
struct Constants
Constants for the exercise screen
-
The length to wait until the first exercise starts
Declaration
Swift
static let timerLength = 3
-
The max chart data displayed at one time
Declaration
Swift
static let chartDataLength = 50
-
The length to wait until the next exercise starts
Declaration
Swift
static let exerciseTimerLength = 10
-
The delta average needed for a B grade
Declaration
Swift
static let exerciseBGrade = 0.035
-
The delta average needed for a C grade
Declaration
Swift
static let exerciseCGrade = 0.055
-
The delta average needed for a D grade
Declaration
Swift
static let exerciseDGrade = 0.085
-
The delta average needed for a F grade
Declaration
Swift
static let exerciseFGrade = 0.140
-
The exercises to complete
Declaration
Swift
static let exercises = [