From 6b17f924e40da6c9ad3b64986f5fa547ac28f8b7 Mon Sep 17 00:00:00 2001 From: Lars Immisch Date: Sun, 16 Apr 2023 00:08:27 +0200 Subject: [PATCH] Release 0.10.0 --- _static/alabaster.css | 4 +- _static/basic.css | 55 ++- _static/doctools.js | 420 ++++++--------------- _static/pygments.css | 10 +- _static/searchtools.js | 823 +++++++++++++++++++++-------------------- _static/underscore.js | 37 +- genindex.html | 47 ++- index.html | 27 +- libalsaaudio.html | 377 +++++++++++++++---- objects.inv | Bin 622 -> 670 bytes py-modindex.html | 13 +- pyalsaaudio.html | 41 +- search.html | 11 +- searchindex.js | 2 +- terminology.html | 71 ++-- 15 files changed, 1032 insertions(+), 906 deletions(-) diff --git a/_static/alabaster.css b/_static/alabaster.css index 0eddaeb..517d0b2 100644 --- a/_static/alabaster.css +++ b/_static/alabaster.css @@ -419,7 +419,9 @@ table.footnote td { } dl { - margin: 0; + margin-left: 0; + margin-right: 0; + margin-top: 0; padding: 0; } diff --git a/_static/basic.css b/_static/basic.css index bf18350..7577acb 100644 --- a/_static/basic.css +++ b/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -222,7 +222,7 @@ table.modindextable td { /* -- general body styles --------------------------------------------------- */ div.body { - min-width: 450px; + min-width: 360px; max-width: 800px; } @@ -237,16 +237,6 @@ a.headerlink { visibility: hidden; } -a.brackets:before, -span.brackets > a:before{ - content: "["; -} - -a.brackets:after, -span.brackets > a:after { - content: "]"; -} - h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, @@ -335,12 +325,16 @@ p.sidebar-title { font-weight: bold; } +nav.contents, +aside.topic, div.admonition, div.topic, blockquote { clear: left; } /* -- topics ---------------------------------------------------------------- */ +nav.contents, +aside.topic, div.topic { border: 1px solid #ccc; padding: 7px; @@ -379,6 +373,8 @@ div.body p.centered { div.sidebar > :last-child, aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; @@ -386,6 +382,8 @@ div.admonition > :last-child { div.sidebar::after, aside.sidebar::after, +nav.contents::after, +aside.topic::after, div.topic::after, div.admonition::after, blockquote::after { @@ -428,10 +426,6 @@ table.docutils td, table.docutils th { border-bottom: 1px solid #aaa; } -table.footnote td, table.footnote th { - border: 0 !important; -} - th { text-align: left; padding-right: 5px; @@ -615,19 +609,26 @@ ul.simple p { margin-bottom: 0; } -dl.footnote > dt, -dl.citation > dt { +aside.footnote > span, +div.citation > span { float: left; - margin-right: 0.5em; } - -dl.footnote > dd, -dl.citation > dd { +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { margin-bottom: 0em; } - -dl.footnote > dd:after, -dl.citation > dd:after { +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { content: ""; clear: both; } @@ -644,10 +645,6 @@ dl.field-list > dt { padding-right: 5px; } -dl.field-list > dt:after { - content: ":"; -} - dl.field-list > dd { padding-left: 0.5em; margin-top: 0em; diff --git a/_static/doctools.js b/_static/doctools.js index e1bfd70..d06a71d 100644 --- a/_static/doctools.js +++ b/_static/doctools.js @@ -2,357 +2,155 @@ * doctools.js * ~~~~~~~~~~~ * - * Sphinx JavaScript utilities for all documentation. + * Base JavaScript utilities for all Sphinx HTML documentation. * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); } - return result; }; -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} - /** * Small JavaScript module for the documentation. */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - this.initOnKeyListeners(); +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); }, /** * i18n support */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, - LOCALE : 'unknown', + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated === 'undefined') - return string; - return (typeof translated === 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated === 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash && $.browser.mozilla) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); - } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists } }, - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) === 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; }, - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - var url = new URL(window.location); - url.searchParams.delete('highlight'); - window.history.replaceState({}, '', url); + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; }, - /** + /** * helper function to focus on search bar */ - focusSearchBar : function() { - $('input[name=q]').first().focus(); + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); }, /** - * make the url absolute + * Initialise the domain index toggle buttons */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this === '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); }, - initOnKeyListeners: function() { + initOnKeyListeners: () => { // only install a listener if it is really needed - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - return; - - $(document).keydown(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box, textarea, dropdown or button - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' - && activeElementType !== 'BUTTON') { - if (event.altKey || event.ctrlKey || event.metaKey) - return; - - if (!event.shiftKey) { - switch (event.key) { - case 'ArrowLeft': - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) - break; - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - break; - case 'ArrowRight': - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) - break; - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - break; - case 'Escape': - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - break; - Documentation.hideSearchWords(); - return false; - } - } - - // some keyboard layouts may need Shift to get / + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { switch (event.key) { - case '/': - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) - break; - Documentation.focusSearchBar(); - return false; + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; } } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } }); - } + }, }; // quick alias for translations -_ = Documentation.gettext; +const _ = Documentation.gettext; -$(document).ready(function() { - Documentation.init(); -}); +_ready(Documentation.init); diff --git a/_static/pygments.css b/_static/pygments.css index d14395e..691aeb8 100644 --- a/_static/pygments.css +++ b/_static/pygments.css @@ -1,8 +1,8 @@ -pre { line-height: 125%; margin: 0; } -td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } -span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; } -td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } -span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; } +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #eeffcc; } .highlight .c { color: #408090; font-style: italic } /* Comment */ diff --git a/_static/searchtools.js b/_static/searchtools.js index 0a44e85..97d56a7 100644 --- a/_static/searchtools.js +++ b/_static/searchtools.js @@ -4,22 +4,24 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ +"use strict"; -if (!Scorer) { - /** - * Simple result scoring code. - */ +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { var Scorer = { // Implement the following function to further tweak the score for each result - // The function takes a result array [filename, title, anchor, descr, score] + // The function takes a result array [docname, title, anchor, descr, score, filename] // and returns the new score. /* - score: function(result) { - return result[4]; + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score }, */ @@ -28,9 +30,11 @@ if (!Scorer) { // or matches in the last dotted part of the object name objPartialMatch: 6, // Additive scores depending on the priority of the object - objPrio: {0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5}, // used to be unimportantResults + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, // Used when the priority is not in the mapping. objPrioDefault: 0, @@ -39,452 +43,495 @@ if (!Scorer) { partialTitle: 7, // query found in terms term: 5, - partialTerm: 2 + partialTerm: 2, }; } -if (!splitQuery) { - function splitQuery(query) { - return query.split(/\s+/); +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings } /** * Search Module */ -var Search = { - - _index : null, - _queued_query : null, - _pulse_status : -1, - - htmlToText : function(htmlString) { - var virtualDocument = document.implementation.createHTMLDocument('virtual'); - var htmlElement = $(htmlString, virtualDocument); - htmlElement.find('.headerlink').remove(); - docContent = htmlElement.find('[role=main]')[0]; - if(docContent === undefined) { - console.warn("Content block not found. Sphinx search tries to obtain it " + - "via '[role=main]'. Could you check your theme or template."); - return ""; - } - return docContent.textContent || docContent.innerText; +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; }, - init : function() { - var params = $.getQueryParameters(); - if (params.q) { - var query = params.q[0]; - $('input[name="q"]')[0].value = query; - this.performSearch(query); - } + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); }, - loadIndex : function(url) { - $.ajax({type: "GET", url: url, data: null, - dataType: "script", cache: true, - complete: function(jqxhr, textstatus) { - if (textstatus != "success") { - document.getElementById("searchindexloader").src = url; - } - }}); - }, + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), - setIndex : function(index) { - var q; - this._index = index; - if ((q = this._queued_query) !== null) { - this._queued_query = null; - Search.query(q); + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); } }, - hasIndex : function() { - return this._index !== null; - }, + hasIndex: () => Search._index !== null, - deferQuery : function(query) { - this._queued_query = query; - }, + deferQuery: (query) => (Search._queued_query = query), - stopPulse : function() { - this._pulse_status = 0; - }, + stopPulse: () => (Search._pulse_status = -1), - startPulse : function() { - if (this._pulse_status >= 0) - return; - function pulse() { - var i; + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { Search._pulse_status = (Search._pulse_status + 1) % 4; - var dotString = ''; - for (i = 0; i < Search._pulse_status; i++) - dotString += '.'; - Search.dots.text(dotString); - if (Search._pulse_status > -1) - window.setTimeout(pulse, 500); - } + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; pulse(); }, /** * perform a search for something (or wait until index is loaded) */ - performSearch : function(query) { + performSearch: (query) => { // create the required interface elements - this.out = $('#search-results'); - this.title = $('

' + _('Searching') + '

').appendTo(this.out); - this.dots = $('').appendTo(this.title); - this.status = $('

 

').appendTo(this.out); - this.output = $(' + + +

D

+ + +
@@ -113,6 +134,14 @@

H

+

I

+ + +
+

M

    @@ -176,6 +205,8 @@

    S

  • set_tstamp_type() (alsaaudio.PCM method)
  • setchannels() (alsaaudio.PCM method) +
  • +
  • setenum() (alsaaudio.Mixer method)
  • setformat() (alsaaudio.PCM method)
  • @@ -190,6 +221,8 @@

    S

  • setrec() (alsaaudio.Mixer method)
  • setvolume() (alsaaudio.Mixer method) +
  • +
  • state() (alsaaudio.PCM method)
  • switchcap() (alsaaudio.Mixer method)
  • @@ -256,7 +289,7 @@

    Quick search

    - + @@ -273,8 +306,8 @@

    Quick search

    ©2017, Lars Immisch & Casper Wilstrup. | - Powered by Sphinx 4.5.0 - & Alabaster 0.7.12 + Powered by Sphinx 6.1.3 + & Alabaster 0.7.13 diff --git a/index.html b/index.html index bb4914a..da8c2be 100644 --- a/index.html +++ b/index.html @@ -1,18 +1,17 @@ - + - + - alsaaudio documentation — alsaaudio documentation 0.9.2 documentation + alsaaudio documentation — alsaaudio documentation 0.10.0 documentation - - + @@ -33,7 +32,7 @@
    -

    alsaaudio documentation

    +

    alsaaudio documentation

    Contents:

    -

    Download

    +

    Download

    -

    Github

    +

    Github

    -

    Indices and tables

    +

    Indices and tables

    - + @@ -137,8 +140,8 @@

    Quick search

    ©2017, Lars Immisch & Casper Wilstrup. | - Powered by Sphinx 4.5.0 - & Alabaster 0.7.12 + Powered by Sphinx 6.1.3 + & Alabaster 0.7.13 | - + - + - alsaaudio — alsaaudio documentation 0.9.2 documentation + alsaaudio — alsaaudio documentation 0.10.0 documentation - - + + @@ -33,7 +33,7 @@
    -

    alsaaudio

    +

    alsaaudio

    The alsaaudio module defines functions and classes for using ALSA.

    @@ -69,13 +69,15 @@
    -alsaaudio.mixers(cardindex=- 1, device='default')
    +alsaaudio.mixers(cardindex=-1, device='default')

    List the available mixers. The arguments are:

    -
      +
      • cardindex - the card index. If this argument is given, the device name is constructed as: ‘hw:cardindex’ and the device keyword argument is ignored. 0 is the first hardware sound -card.

      • +card.

        +

        Note: This should not be used, as it bypasses most of ALSA’s configuration.

        +
      • device - the name of the device on which the mixer resides. The default is 'default'.

      @@ -110,13 +112,13 @@
    -

    PCM Objects

    +

    PCM Objects

    PCM objects in alsaaudio can play or capture (record) PCM sound through speakers or a microphone. The PCM constructor takes the following arguments:

    -class alsaaudio.PCM(type=PCM_PLAYBACK, mode=PCM_NORMAL, rate=44100, channels=2, format=PCM_FORMAT_S16_LE, periodsize=32, device='default', cardindex=- 1)
    +class alsaaudio.PCM(type=PCM_PLAYBACK, mode=PCM_NORMAL, rate=44100, channels=2, format=PCM_FORMAT_S16_LE, periodsize=32, periods=4, device='default', cardindex=-1)

    This class is used to represent a PCM device (either for playback and recording). The arguments are:

      @@ -130,10 +132,6 @@ The default value is PCM_FORMAT_S16_LE.

    ---- @@ -144,7 +142,7 @@ - + @@ -223,17 +221,27 @@

    Format

    Description

    Signed 8 bit samples for each channel

    PCM_FORMAT_U8

    Signed 8 bit samples for each channel

    Unsigned 8 bit samples for each channel

    PCM_FORMAT_S16_LE

    Signed 16 bit samples for each channel Little Endian byte order)

    -
      -
    • periodsize - the period size in frames. Each write should consist of periodsize frames. The default value is 32.

    • +
        +
      • periodsize - the period size in frames. +Make sure you understand the meaning of periods. +The default value is 32, which is below the actual minimum of most devices, +and will therefore likely be larger in practice.

      • +
      • periods - the number of periods in the buffer. The default value is 4.

      • device - the name of the PCM device that should be used (for example a value from the output of pcms()). The default value is 'default'.

      • cardindex - the card index. If this argument is given, the device name is constructed as ‘hw:cardindex’ and the device keyword argument is ignored. -0 is the first hardware sound card.

      • +0 is the first hardware sound card.

        +

        Note: This should not be used, as it bypasses most of ALSA’s configuration.

        +

      This will construct a PCM object with the given settings.

      +

      Changed in 0.10:

      +
        +
      • Added the optional named parameter periods.

      • +

      Changed in 0.9:

      • Added the optional named parameters rate, channels, format and periodsize.

      • @@ -249,6 +257,159 @@

    PCM objects have the following methods:

    +
    +
    +PCM.info()
    +

    The info function returns a dictionary containing the configuration of a PCM device. As ALSA takes into account limitations of the hardware and software devices the configuration achieved might not correspond to the values used during creation. There is therefore a need to check the realised configuration before processing the sound coming from the device or before sending sound to a device. A small subset of parameters can be set, but cannot be queried. These parameters are stored by alsaaudio and returned as they were given by the user, to distinguish them from parameters retrieved from ALSA these parameters have a name prefixed with “ (call value) “. Yet another set of properties derives directly from the hardware and can be obtained through ALSA.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    Key

    Description (Reference)

    Type

    name

    PCM():device

    string

    card_no

    index of card

    integer (negative indicates device not associable with a card)

    device_no

    index of PCM device

    integer

    subdevice_no

    index of PCM subdevice

    integer

    state

    name of PCM state

    string

    access_type

    name of PCM access type

    string

    (call value) type

    PCM():type

    integer

    (call value) type_name

    PCM():type

    string

    (call value) mode

    PCM():mode

    integer

    (call value) mode_name

    PCM():mode

    string

    format

    PCM():format

    integer

    format_name

    PCM():format

    string

    format_description

    PCM():format

    string

    subformat_name

    name of PCM subformat

    string

    subformat_description

    description of subformat

    string

    channels

    PCM():channels

    integer

    rate

    PCM():rate

    integer (Hz)

    period_time

    period duration

    integer (\(\mu s\))

    period_size

    PCM():period_size

    integer (frames)

    buffer_time

    buffer time

    integer (\(\mu s\)) (negative indicates error)

    buffer_size

    buffer size

    integer (frames) (negative indicates error)

    get_periods

    approx. periods in buffer

    integer (negative indicates error)

    rate_numden

    numerator, denominator

    tuple (integer (Hz), integer (Hz))

    significant_bits

    significant bits in sample

    integer (negative indicates error)

    is_batch

    hw: double buffering

    boolean (True: hardware supported)

    is_block_transfer

    hw: block transfer

    boolean (True: hardware supported)

    is_double

    hw: double buffering

    boolean (True: hardware supported)

    is_half_duplex

    hw: half-duplex

    boolean (True: hardware supported)

    is_joint_duplex

    hw: joint-duplex

    boolean (True: hardware supported)

    can_overrange

    hw: overrange detection

    boolean (True: hardware supported)

    can_mmap_sample_resolution

    hw: sample-resol. mmap

    boolean (True: hardware supported)

    can_pause

    hw: pause

    boolean (True: hardware supported)

    can_resume

    hw: resume

    boolean (True: hardware supported)

    can_sync_start

    hw: synchronized start

    boolean (True: hardware supported)

    +

    The italicized descriptions give a summary of the “full” description as it can be found in the ALSA documentation. “hw:”: indicates that the property indicated relates to the hardware. Parameters passed to the PCM object during instantation are prefixed with “PCM():”, they are described there for the keyword argument indicated after “PCM():”.

    +
    +
    PCM.pcmtype()
    @@ -301,6 +462,38 @@
    +
    +
    +PCM.info()
    +

    Returns a dictionary with the PCM object’s configured parameters.

    +

    Values are retrieved from the ALSA library if they are available; +otherwise they represent those stored by pyalsaaudio, and their keys +are prefixed with ‘ (call value) ‘.

    +

    New in 0.9.1

    +
    + +
    +
    +PCM.dumpinfo()
    +

    Dumps the PCM object’s configured parameters to stdout.

    +
    + +
    +
    +PCM.state()
    +

    Returs the current state of the stream, which can be one of +PCM_STATE_OPEN (this should not actually happen), +PCM_STATE_SETUP (after drop() or drain()), +PCM_STATE_PREPARED (after construction), +PCM_STATE_RUNNING, +PCM_STATE_XRUN, +PCM_STATE_DRAINING, +PCM_STATE_PAUSED, +PCM_STATE_SUSPENDED, and +PCM_STATE_DISCONNECTED.

    +

    New in 0.10

    +
    +
    PCM.read()
    @@ -331,6 +524,9 @@

    In PCM_NONBLOCK mode, the call will return immediately, with a return value of zero, if the buffer is full. In this case, the data should be written at a later time.

    +

    Note that this call completing means only that the samples were buffered +in the kernel, and playout will continue afterwards. Make sure that the +stream is drained before discarding the PCM handle.

    @@ -340,12 +536,37 @@ Otherwise, playback/capture is resumed.

    +
    +
    +PCM.drop()
    +

    Stop the stream and drop residual buffered frames.

    +

    New in 0.9

    +
    + +
    +
    +PCM.drain()
    +

    For PCM_PLAYBACK PCM objects, play residual buffered frames +and then stop the stream. In PCM_NORMAL mode, +this function blocks until all pending playback is drained.

    +

    For PCM_CAPTURE PCM objects, this function is not very useful.

    +

    New in 0.10

    +
    + +
    +
    +PCM.close()
    +

    Closes the PCM device.

    +

    For PCM_PLAYBACK PCM objects in PCM_NORMAL mode, +this function blocks until all pending playback is drained.

    +
    +
    PCM.polldescriptors()
    -

    Returns a tuple of (file descriptor, eventmask) that can be used to -wait for changes on the PCM with select.poll.

    -

    The eventmask value is compatible with poll.register in the Python +

    Returns a list of tuples of (file descriptor, eventmask) that can be +used to wait for changes on the PCM with select.poll.

    +

    The eventmask value is compatible with `poll.register`__ in the Python select module.

    @@ -385,10 +606,6 @@

    Return a Python tuple (seconds, nanoseconds, frames_available_in_buffer).

    The type of output is controlled by the tstamp_type, as described in the table below.

    ---- @@ -411,10 +628,6 @@

    Timestamp Type

    Description

    The timestamp mode is controlled by the tstamp_mode, as described in the table below.

    ---- @@ -455,11 +668,11 @@ to check how much time has really passed, and add extra writes as nessecary.

    -

    Mixer Objects

    +

    Mixer Objects

    Mixer objects provides access to the ALSA mixer API.

    -class alsaaudio.Mixer(control='Master', id=0, cardindex=- 1, device='default')
    +class alsaaudio.Mixer(control='Master', id=0, cardindex=-1, device='default')

    Arguments are:

    • control - specifies which control to manipulate using this mixer @@ -508,10 +721,6 @@

      Returns a list of the switches which are defined by this specific mixer. Possible values in this list are:

    Timestamp Mode

    Description

    ---- @@ -551,10 +760,6 @@

    Returns a list of the volume control capabilities of this mixer. Possible values in the list are:

    Switch

    Description

    ---- @@ -610,47 +815,45 @@
    -
    -Mixer.getmute()
    -

    Return a list indicating the current mute setting for each -channel. 0 means not muted, 1 means muted.

    -

    This method will fail if the mixer has no playback switch capabilities.

    +
    +Mixer.setenum(index)
    +

    For enumerated controls, sets the currently selected item. +index is an index into the list of available enumerated items returned +by getenum().

    -Mixer.getrange(pcmtype=PCM_PLAYBACK)
    -

    Return the volume range of the ALSA mixer controlled by this object.

    +Mixer.getrange(pcmtype=PCM_PLAYBACK, units=VOLUME_UNITS_RAW) +

    Return the volume range of the ALSA mixer controlled by this object. +The value is a tuple of integers whose meaning is determined by the +units argument.

    The optional pcmtype argument can be either PCM_PLAYBACK or PCM_CAPTURE, which is relevant if the mixer can control both playback and capture volume. The default value is PCM_PLAYBACK if the mixer has playback channels, otherwise it is PCM_CAPTURE.

    -
    - -
    -
    -Mixer.getrec()
    -

    Return a list indicating the current record mute setting for each channel. 0 -means not recording, 1 means recording.

    -

    This method will fail if the mixer has no capture switch capabilities.

    +

    The optional units argument can be one of VOLUME_UNITS_PERCENTAGE, +VOLUME_UNITS_RAW, or VOLUME_UNITS_DB.

    -Mixer.getvolume(pcmtype=PCM_PLAYBACK)
    +Mixer.getvolume(pcmtype=PCM_PLAYBACK, units=VOLUME_UNITS_PERCENTAGE)

    Returns a list with the current volume settings for each channel. The list -elements are integer percentages.

    +elements are integers whose meaning is determined by the units argument.

    The optional pcmtype argument can be either PCM_PLAYBACK or PCM_CAPTURE, which is relevant if the mixer can control both playback and capture volume. The default value is PCM_PLAYBACK if the mixer has playback channels, otherwise it is PCM_CAPTURE.

    +

    The optional units argument can be one of VOLUME_UNITS_PERCENTAGE, +VOLUME_UNITS_RAW, or VOLUME_UNITS_DB.

    -Mixer.setvolume(volume, channel=None, pcmtype=PCM_PLAYBACK)
    +Mixer.setvolume(volume, channel=None, pcmtype=PCM_PLAYBACK, units=VOLUME_UNITS_PERCENTAGE)

    Change the current volume settings for this mixer. The volume argument -controls the new volume setting as an integer percentage.

    +is an integer whose meaning is determined by the units argument.

    If the optional argument channel is present, the volume is set only for this channel. This assumes that the mixer can control the volume for the channels independently.

    @@ -658,6 +861,16 @@ PCM_CAPTURE, which is relevant if the mixer can control both playback and capture volume. The default value is PCM_PLAYBACK if the mixer has playback channels, otherwise it is PCM_CAPTURE.

    +

    The optional units argument can be one of VOLUME_UNITS_PERCENTAGE, +VOLUME_UNITS_RAW, or VOLUME_UNITS_DB.

    +
    + +
    +
    +Mixer.getmute()
    +

    Return a list indicating the current mute setting for each channel. +0 means not muted, 1 means muted.

    +

    This method will fail if the mixer has no playback switch capabilities.

    @@ -670,6 +883,14 @@

    This method will fail if the mixer has no playback mute capabilities

    +
    +
    +Mixer.getrec()
    +

    Return a list indicating the current record mute setting for each channel. +0 means not recording, 1 means recording.

    +

    This method will fail if the mixer has no capture switch capabilities.

    +
    +
    Mixer.setrec(capture[, channel])
    @@ -683,20 +904,26 @@
    Mixer.polldescriptors()
    -

    Returns a tuple of (file descriptor, eventmask) that can be used to -wait for changes on the mixer with select.poll.

    -

    The eventmask value is compatible with poll.register in the Python +

    Returns a list of tuples of (file descriptor, eventmask) that can be +used to wait for changes on the mixer with select.poll.

    +

    The eventmask value is compatible with `poll.register`__ in the Python select module.

    Mixer.handleevents()
    -

    Acknowledge events on the polldescriptors file descriptors +

    Acknowledge events on the polldescriptors() file descriptors to prevent subsequent polls from returning the same events again. Returns the number of events that were acknowledged.

    +
    +
    +Mixer.close()
    +

    Closes the Mixer device.

    +
    +

    A rant on the ALSA Mixer API

    The ALSA mixer API is extremely complicated - and hardly documented at all. alsaaudio implements a much simplified way to access this API. In @@ -716,7 +943,7 @@ painful trial and error process.

    -

    Examples

    +

    Examples

    The following example are provided:

    • playwav.py

    • @@ -740,7 +967,7 @@

      mixertest.py accepts the commandline options -d <device> and -c <cardindex>.

      -

      playwav.py

      +

      playwav.py

      playwav.py plays a wav file.

      To test PCM playback (on your default soundcard), run:

      $ python playwav.py <wav file>
      @@ -748,7 +975,7 @@ 

      playwav.py -

      recordtest.py and playbacktest.py

      +

      recordtest.py and playbacktest.py

      recordtest.py and playbacktest.py will record and play a raw sound file in CD quality.

      To test PCM recordings (on your default soundcard), run:

      @@ -763,7 +990,7 @@

      recordtest.py and playbacktest.py -

      mixertest.py

      +

      mixertest.py

      Without arguments, mixertest.py will list all available controls on the default soundcard.

      The output might look like this:

      @@ -814,12 +1041,6 @@

      mixertest.pyFootnotes

      -
      -
      1
      -

      ALSA also allows PCM_ASYNC, but this is not supported yet.

      -
      -

    @@ -849,6 +1070,10 @@

    Navigation

  • Testing
  • PCM Terminology and Concepts
  • alsaaudio
      +
    • pcms()
    • +
    • cards()
    • +
    • mixers()
    • +
    • asoundlib_version()
    • PCM Objects
    • Mixer Objects
    • Examples
    • @@ -873,7 +1098,7 @@

      Quick search

      - + @@ -890,8 +1115,8 @@

      Quick search

      ©2017, Lars Immisch & Casper Wilstrup. | - Powered by Sphinx 4.5.0 - & Alabaster 0.7.12 + Powered by Sphinx 6.1.3 + & Alabaster 0.7.13 | # delta 490 zcmVTB*&l^vDH2O>4YQM6!x$f-L1wsOa=7{Wh zg7CXRPz2?p3pJjxy0}2?Qd{Pmj%2CY?y4h2r0f8ST-0wUH-x&C=Tv z{m=9D4b5~etvmh(K_B27TWhK2pQs;M-cWC?q~phS-pJ8*`A;n;Tt;Ww!i74ER_=y- z%R-!}hfSvM$82$7=8nt#NY~eXGCQsw=;zv!ItJpVOVS|lAo|;Ac`b{7=KVeIpotKS gvQE2hTn1Py|20P`{aR@0uZg`nE5K8ZAG}TR1V&8qf&c&j diff --git a/py-modindex.html b/py-modindex.html index 0cde73c..33d57e2 100644 --- a/py-modindex.html +++ b/py-modindex.html @@ -1,17 +1,16 @@ - + - Python Module Index — alsaaudio documentation 0.9.2 documentation + Python Module Index — alsaaudio documentation 0.10.0 documentation - - + @@ -98,7 +97,7 @@

      Quick search

      - + @@ -115,8 +114,8 @@

      Quick search

      ©2017, Lars Immisch & Casper Wilstrup. | - Powered by
      Sphinx 4.5.0 - & Alabaster 0.7.12 + Powered by Sphinx 6.1.3 + & Alabaster 0.7.13 diff --git a/pyalsaaudio.html b/pyalsaaudio.html index 1f10d65..6f68935 100644 --- a/pyalsaaudio.html +++ b/pyalsaaudio.html @@ -1,18 +1,17 @@ - + - + - Introduction — alsaaudio documentation 0.9.2 documentation + Introduction — alsaaudio documentation 0.10.0 documentation - - + @@ -34,30 +33,30 @@
      -

      Introduction

      +

      Introduction

      -
      Author
      +
      Author:

      Casper Wilstrup <cwi@aves.dk>

      -
      Author
      +
      Author:

      Lars Immisch <lars@ibp.de>

      This software is licensed under the PSF license - the same one used by the majority of the python distribution. Basically you can use it for anything you wish (even commercial purposes). There is no warranty whatsoever.

      -
      +
      +
      -

      What is ALSA

      +

      What is ALSA

      The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI functionality to the Linux operating system.

      Logically ALSA consists of these components:

      @@ -73,9 +72,9 @@

      What is ALSAhttp://www.alsa-project.org

      -

      ALSA and Python

      -

      The older Linux sound API (OSS) which is now deprecated is well supported from -the standard Python library, through the ossaudiodev module. No native ALSA +

      ALSA and Python

      +

      The older Linux sound API (OSS) – which is now deprecated – is well supported +by the standard Python library, through the ossaudiodev module. No native ALSA support exists in the standard library.

      There are a few other “ALSA for Python” projects available, including at least two different projects called pyAlsa. Neither of these seem to be under active @@ -90,7 +89,7 @@

      ALSA and Python -

      Installation

      +

      Installation

      Note: the wrappers link with the alsasound library (from the alsa-lib package) and need the ALSA headers for compilation. Verify that you have /usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.

      @@ -109,7 +108,7 @@

      Installation -

      Testing

      +

      Testing

      Make sure that aplay plays a file through the soundcard you want, then try:

      diff --git a/searchindex.js b/searchindex.js index e47de22..86e482a 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index","libalsaaudio","pyalsaaudio","terminology"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":5,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["index.rst","libalsaaudio.rst","pyalsaaudio.rst","terminology.rst"],objects:{"":[[1,0,0,"-","alsaaudio"]],"alsaaudio.Mixer":[[1,2,1,"","cardname"],[1,2,1,"","getenum"],[1,2,1,"","getmute"],[1,2,1,"","getrange"],[1,2,1,"","getrec"],[1,2,1,"","getvolume"],[1,2,1,"","handleevents"],[1,2,1,"","mixer"],[1,2,1,"","mixerid"],[1,2,1,"","polldescriptors"],[1,2,1,"","setmute"],[1,2,1,"","setrec"],[1,2,1,"","setvolume"],[1,2,1,"","switchcap"],[1,2,1,"","volumecap"]],"alsaaudio.PCM":[[1,2,1,"","cardname"],[1,2,1,"","get_tstamp_mode"],[1,2,1,"","get_tstamp_type"],[1,2,1,"","htimestamp"],[1,2,1,"","pause"],[1,2,1,"","pcmmode"],[1,2,1,"","pcmtype"],[1,2,1,"","polldescriptors"],[1,2,1,"","read"],[1,2,1,"","set_tstamp_mode"],[1,2,1,"","set_tstamp_type"],[1,2,1,"","setchannels"],[1,2,1,"","setformat"],[1,2,1,"","setperiodsize"],[1,2,1,"","setrate"],[1,2,1,"","write"]],alsaaudio:[[1,1,1,"","Mixer"],[1,1,1,"","PCM"],[1,3,1,"","asoundlib_version"],[1,3,1,"","cards"],[1,3,1,"","mixers"],[1,3,1,"","pcms"]]},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:function"},terms:{"0":[1,2],"1":[1,3],"10":1,"16":1,"16000":1,"2":[1,2],"24":1,"3":1,"32":[1,3],"4":[1,2],"40":1,"44100":[1,3],"4608":3,"48":3,"48000":1,"5":[2,3],"6":[2,3],"61":1,"64":[1,3],"64kbit":3,"8":[1,3],"8000":[1,3],"9":1,"9600":1,"96000":[1,3],"byte":[1,3],"case":1,"class":1,"default":[1,2],"do":[1,2],"enum":1,"float":[1,3],"function":[1,2],"import":[1,3],"long":2,"new":[1,3],"return":[1,3],"switch":1,"true":1,"try":[1,2],"while":3,A:[1,2,3],And:[1,2],As:1,At:[1,3],For:[1,3],If:[1,2,3],In:[1,3],It:2,No:[1,2],Not:[1,3],On:2,One:1,Or:1,The:[1,2,3],There:2,These:2,To:[1,2],With:[1,3],abl:1,about:2,accept:1,access:[1,2],accummul:1,accumul:1,achiev:1,acknowledg:1,activ:2,actual:[1,3],ad:1,add:1,advanc:2,affair:1,after:1,again:1,all:[1,2,3],allow:1,almost:3,alsa:[0,1,3],alsaaudio:3,alsasound:2,also:[1,2,3],although:2,alwai:1,amix:1,amplitud:3,an:[1,3],ani:[1,2],annoi:1,anoth:1,anyth:2,api:[1,2,3],aplai:[1,2],applic:2,appreci:2,ar:[1,2,3],architectur:2,arecord:1,argument:[1,2],asoundlib_vers:1,associ:1,assum:1,au:1,audio:[1,2,3],author:2,aux:1,av:2,avail:[1,2],avoid:1,back:[1,2],basic:2,becaus:1,becom:1,been:[1,2],befor:2,behaviour:1,below:1,best:1,better:1,between:3,big:[1,3],bit:[1,2,3],block:1,both:1,broke:1,buffer:[1,3],bug:[0,2],build:2,c:[1,2],call:[1,2],can:[1,2,3],cannot:1,capabl:[1,2],captur:[1,2,3],card:[1,2],cardindex:1,cardnam:1,casper:2,cd:[1,3],certain:3,chang:1,channel:[1,3],check:1,choic:1,chois:1,chosen:1,chunk:3,click:1,clock:1,come:1,commandlin:1,commerci:2,common:1,compat:1,compil:2,complet:2,complex:1,complic:1,compon:2,compress:1,concept:0,configur:[2,3],consist:[1,2,3],constant:1,construct:1,constructor:1,contain:[1,2,3],control:[1,3],convers:[1,3],copi:3,correspond:1,could:1,coupl:1,cpu:3,creat:1,ctl:[1,2],current:[1,2,3],cwi:2,d:[1,2,3],data:[1,3],de:2,debian:2,defin:1,delai:1,demand:3,depend:2,deprec:[1,2],describ:1,descript:1,descriptor:1,design:1,determin:[1,3],dev:2,develop:2,devic:[1,2,3],differ:[1,2,3],difficult:2,direct:3,directli:3,displai:1,distribut:2,dk:2,document:1,doe:1,doesn:1,don:2,done:3,driver:2,dynam:3,each:[1,3],easi:1,either:[1,3],elabor:1,element:1,empti:1,enabl:1,encod:1,end:3,endian:[1,3],enough:1,enumer:1,epip:1,epoch:1,equival:1,error:1,etc:[1,3],even:[1,2],event:1,eventmask:1,everi:[1,3],exactli:[1,3],exampl:[0,3],except:1,exclus:1,execut:2,exist:2,expir:1,extra:1,extrem:1,fail:[1,2],fairli:2,familiar:3,featur:2,few:[1,2],file:[1,2],filenam:[1,2],fill:2,find:[1,2],first:1,flag:1,flow:3,follow:[1,2],foo:1,footnot:1,format:[1,3],found:[1,2],fragil:1,frame:[1,3],frames:1,frames_available_in_buff:1,from:[0,1,2,3],full:[1,2],futur:1,gap:2,gener:3,get:1,get_tstamp_mod:1,get_tstamp_typ:1,getenum:1,getmut:1,getrang:1,getrec:1,getvolum:1,give:1,given:1,goal:2,greatli:2,guess:1,gui:1,ha:[1,2,3],had:1,half:1,handl:[2,3],handleev:1,happen:1,hardli:1,hardwar:[1,2,3],have:[1,2],header:2,headphon:1,hint:1,homepag:2,horribl:1,how:[1,3],howev:1,howto:1,htimestamp:1,http:2,hw:[1,2],hz:[1,3],i:[1,2],ibp:2,id:1,ignor:1,immedi:1,immisch:2,impact:3,implement:[1,2],implic:3,includ:2,incorpor:1,independ:1,index:[0,1],indic:[1,2],individu:3,inform:2,input:3,instal:0,instead:1,integ:[1,3],interact:1,intern:3,interpret:1,interrupt:[1,2,3],interv:3,introduct:0,issu:2,item0:1,item:1,itself:1,join:1,just:1,kb:3,kernel:[1,2,3],keyword:1,know:1,known:3,l:1,lar:2,larger:[1,3],last:1,latenc:3,later:[1,2],layer:3,least:[1,2],legitim:1,length:1,less:1,let:1,level:2,lib:2,libasound2:2,libasound:2,librari:2,licens:2,like:[1,2],limit:1,line:1,link:2,linux:2,list:[1,2],littl:[1,3],logarithm:1,logic:2,look:[1,2],lost:1,lot:[1,3],loudest:3,low:[2,3],m:1,mai:[1,2],mainli:1,major:2,make:[1,2],mani:3,manipul:[1,2],master:1,match:1,mb:3,me:[1,2],mean:[1,3],memori:3,method:1,mic:1,microphon:[1,2],midi:2,might:1,minim:2,mix:1,mixer:[0,2],mixerid:1,mode:1,moder:1,modul:[0,1,2],mono:[1,3],monoton:1,more:[1,2],most:[1,2],mpeg:1,much:[1,3],multimedia:1,multipl:[1,3],music:3,must:[1,3],mute:1,my:[1,2],myself:1,name:1,nanosecond:1,nativ:2,natur:2,nchannel:1,necessari:3,need:[1,2],neg:1,neither:2,nessecari:1,net:1,none:1,note:[1,2],noth:[1,3],now:2,ntp:1,number:[1,3],object:0,occur:1,often:3,older:2,onc:3,one:[1,2,3],onli:[1,3],oper:[1,2],option:1,order:[1,3],org:2,oss:2,ossaudiodev:2,other:[1,2,3],otherwis:1,our:2,out:1,output:[1,3],overrun:1,own:2,packag:2,page:0,pain:1,paramet:1,pass:1,patch:2,path:2,paus:1,pc:1,pcm:[0,2],pcm_async:1,pcm_captur:1,pcm_format_a_law:1,pcm_format_float64_b:1,pcm_format_float64_l:1,pcm_format_float_b:1,pcm_format_float_l:1,pcm_format_gsm:1,pcm_format_ima_adpcm:1,pcm_format_mpeg:1,pcm_format_mu_law:1,pcm_format_s16_b:1,pcm_format_s16_l:1,pcm_format_s24_3b:1,pcm_format_s24_3l:1,pcm_format_s24_b:1,pcm_format_s24_l:1,pcm_format_s32_b:1,pcm_format_s32_l:1,pcm_format_s8:1,pcm_format_u16_b:1,pcm_format_u16_l:1,pcm_format_u24_3b:1,pcm_format_u24_3l:1,pcm_format_u24_b:1,pcm_format_u24_l:1,pcm_format_u32_b:1,pcm_format_u32_l:1,pcm_format_u8:1,pcm_nonblock:1,pcm_normal:1,pcm_playback:1,pcm_tstamp_en:1,pcm_tstamp_non:1,pcm_tstamp_type_gettimeofdai:1,pcm_tstamp_type_monoton:1,pcm_tstamp_type_monotonic_raw:1,pcmmode:1,pcmtype:1,per:3,percentag:1,period:[1,3],periods:1,physic:2,plai:[1,2,3],playback:[1,2],playbacktest:2,player:1,playout:1,playwav:2,pleas:[1,2],point:3,poll:1,polldescriptor:1,posit:1,possibl:1,precis:3,preload:1,present:1,prevent:1,prioriti:2,probabl:2,problem:[1,2],process:[1,3],program:1,progress:1,project:2,proper:2,provid:[1,2,3],psf:2,purpos:[1,2],put:1,py:2,pyalsa:2,pyalsaaudio:2,pypi:0,python:[0,1],qualiti:1,quietest:3,quit:1,rang:[1,3],rant:1,rate:[1,3],ratio:1,raw:1,re:3,read:[1,3],readi:3,real:[1,2],realli:1,realtim:1,rear:1,reason:1,record:[1,2,3],recordtest:2,reexpos:1,regard:2,regist:1,relev:1,replac:3,report:2,repositori:0,repres:[1,3],requir:2,resid:1,resourc:3,respons:2,resproduc:3,result:1,resum:1,root:2,run:1,s:[1,2,3],same:[1,2,3],sampl:[1,3],scale:3,search:0,second:[1,3],see:1,seem:2,select:1,send:2,separ:1,sequenc:2,set:[1,2,3],set_tstamp_mod:1,set_tstamp_typ:1,setchannel:1,setformat:1,setmut:1,setperiods:1,setrat:1,setrec:1,setup:[1,2],setvolum:1,sever:2,ship:2,should:[1,2,3],sign:1,signal:3,signific:3,similar:2,similarli:3,simpl:1,simpli:3,simplifi:[1,2],sinc:[1,2,3],singl:[1,3],size:[1,3],slightli:1,slower:3,small:3,sndrpihifiberri:2,so:[1,2,3],softwar:2,sole:1,some:[1,3],somebodi:1,someth:1,sound:[1,2,3],soundcard:[1,2],space:2,speak:[1,2],speaker:1,specif:[1,2,3],specifi:1,speech:1,stai:1,standard:2,start:1,state:1,stereo:[1,3],still:1,strategi:1,string:1,subsequ:1,subtli:1,succeed:1,suit:2,sun:1,support:[1,2],sure:[1,2],switchcap:1,synchron:1,system:[1,2],t:[1,2],tabl:1,take:1,taken:3,task:1,team:2,telephoni:[1,3],term:2,terminolog:0,test:[0,1],th:1,than:1,thegithub:2,thei:3,therefor:3,thi:[1,2,3],those:2,thread:1,through:[1,2],time:[1,2,3],timeout:1,timer:1,timestamp:1,too:1,tracker:[0,2],trial:1,tstamp_mod:1,tstamp_typ:1,tupl:1,two:[1,2,3],type:1,typic:[1,3],ubuntu:2,ugli:1,under:2,underli:1,underrun:1,understand:[1,3],unfortun:1,unlik:2,unsign:1,unspecifi:1,until:1,updat:1,us:[1,2,3],usag:3,usecas:1,user:2,userspac:[2,3],usr:2,usual:3,util:3,valid:1,valu:1,vari:3,ve:1,veri:[2,3],verifi:2,version:[1,2],virtual:1,volum:1,volumecap:1,volumn:1,volunt:2,wa:1,wai:1,wait:1,want:[1,2],warranti:2,wav:[1,2],we:3,welcom:2,well:2,were:1,what:[0,1],whatsoev:2,when:3,where:1,whether:3,which:[1,2,3],wide:1,wilstrup:2,wish:2,within:2,without:[1,2],work:2,would:[1,2,3],wrapper:2,write:[1,3],written:1,wrote:2,www:2,yet:1,you:[1,2,3],your:[1,2],yourself:2,zero:1},titles:["alsaaudio documentation","alsaaudio","Introduction","PCM Terminology and Concepts"],titleterms:{"abstract":2,alsa:2,alsaaudio:[0,1],concept:3,content:0,document:0,download:0,exampl:1,github:0,indic:0,instal:2,introduct:2,mixer:1,mixertest:1,object:1,pcm:[1,3],playbacktest:1,playwav:1,py:1,python:2,recordtest:1,tabl:0,terminolog:3,test:2,what:2}}) \ No newline at end of file +Search.setIndex({"docnames": ["index", "libalsaaudio", "pyalsaaudio", "terminology"], "filenames": ["index.rst", "libalsaaudio.rst", "pyalsaaudio.rst", "terminology.rst"], "titles": ["alsaaudio documentation", "alsaaudio", "Introduction", "PCM Terminology and Concepts"], "terms": {"introduct": 0, "what": [0, 1], "i": [0, 1, 3], "alsa": [0, 1], "python": [0, 1], "instal": 0, "test": [0, 1], "pcm": [0, 2], "terminologi": 0, "concept": 0, "card": [0, 1, 2], "mixer": [0, 2], "asoundlib_vers": [0, 1], "object": 0, "exampl": [0, 3], "from": [0, 1, 2, 3], "pypi": 0, "repositori": 0, "bug": [0, 2], "tracker": [0, 2], "index": [0, 1], "modul": [0, 1, 2], "search": 0, "page": 0, "The": [1, 2, 3], "defin": 1, "function": [1, 2], "class": 1, "us": [1, 2, 3], "pcmtype": 1, "pcm_playback": 1, "list": [1, 2], "avail": [1, 2], "devic": [1, 2, 3], "name": 1, "argument": [1, 2], "ar": [1, 2, 3], "can": [1, 2, 3], "either": [1, 3], "pcm_captur": 1, "default": [1, 2], "note": [1, 2], "For": [1, 3], "should": [1, 2, 3], "equival": 1, "aplai": [1, 2], "l": 1, "displai": 1, "commandlin": 1, "arecord": 1, "new": [1, 3], "0": [1, 2], "8": [1, 3], "thi": [1, 2, 3], "onli": [1, 3], "moder": 1, "If": [1, 2, 3], "you": [1, 2, 3], "want": [1, 2], "see": 1, "instead": 1, "cardindex": 1, "1": [1, 3], "given": [1, 3], "construct": 1, "hw": [1, 2], "keyword": 1, "ignor": 1, "first": 1, "hardwar": [1, 2, 3], "sound": [1, 2, 3], "bypass": 1, "most": [1, 2], "": [1, 2, 3], "configur": [1, 2, 3], "which": [1, 2, 3], "resid": 1, "control": [1, 3], "also": [1, 2, 3], "amix": 1, "To": [1, 2], "elabor": 1, "call": [1, 2, 3], "give": 1, "same": [1, 2], "c": [1, 2], "And": [1, 2], "foo": 1, "d": [1, 2], "chang": 1, "select": 1, "virtual": 1, "As": 1, "result": 1, "behaviour": 1, "ha": [1, 2, 3], "subtli": 1, "sinc": [1, 2], "return": [1, 3], "string": 1, "contain": [1, 2, 3], "version": [1, 2], "found": [1, 2], "plai": [1, 2, 3], "captur": [1, 2, 3], "record": [1, 2], "through": [1, 2], "speaker": 1, "microphon": [1, 2], "constructor": 1, "take": [1, 3], "follow": [1, 2], "type": 1, "mode": 1, "pcm_normal": 1, "rate": [1, 3], "44100": [1, 3], "channel": [1, 3], "2": [1, 2], "format": [1, 3], "pcm_format_s16_l": 1, "periods": 1, "32": [1, 3], "period": [1, 3], "4": [1, 2], "repres": [1, 3], "playback": [1, 2, 3], "pcm_nonblock": 1, "sampl": [1, 3], "hz": [1, 3], "typic": [1, 3], "valu": 1, "8000": [1, 3], "mainli": 1, "telephoni": [1, 3], "16000": 1, "48000": 1, "96000": [1, 3], "number": [1, 3], "stereo": [1, 3], "data": [1, 3], "how": [1, 3], "interpret": 1, "encod": 1, "descript": 1, "pcm_format_s8": 1, "sign": 1, "bit": [1, 2, 3], "each": [1, 3], "pcm_format_u8": 1, "unsign": 1, "16": 1, "littl": [1, 3], "endian": [1, 3], "byte": [1, 3], "order": [1, 3], "pcm_format_s16_b": 1, "big": [1, 3], "pcm_format_u16_l": 1, "pcm_format_u16_b": 1, "pcm_format_s24_l": 1, "24": 1, "pcm_format_s24_b": 1, "pcm_format_u24_l": 1, "pcm_format_u24_b": 1, "pcm_format_s32_l": 1, "pcm_format_s32_b": 1, "pcm_format_u32_l": 1, "pcm_format_u32_b": 1, "pcm_format_float_l": 1, "float": [1, 3], "pcm_format_float_b": 1, "pcm_format_float64_l": 1, "64": [1, 3], "pcm_format_float64_b": 1, "pcm_format_mu_law": 1, "A": [1, 2, 3], "logarithm": 1, "sun": 1, "au": 1, "file": [1, 2], "pcm_format_a_law": 1, "anoth": 1, "pcm_format_ima_adpcm": 1, "compress": 1, "interact": 1, "multimedia": 1, "associ": 1, "pcm_format_mpeg": 1, "mpeg": 1, "audio": [1, 2, 3], "pcm_format_gsm": 1, "9600": 1, "constant": 1, "speech": 1, "pcm_format_s24_3l": 1, "3": 1, "pcm_format_s24_3b": 1, "pcm_format_u24_3l": 1, "pcm_format_u24_3b": 1, "size": [1, 3], "frame": [1, 3], "make": [1, 2], "sure": [1, 2], "understand": [1, 3], "mean": [1, 3], "below": 1, "actual": [1, 3], "minimum": 1, "therefor": [1, 3], "like": [1, 2], "larger": 1, "practic": 1, "buffer": [1, 3], "output": [1, 3], "set": [1, 2, 3], "10": 1, "ad": 1, "option": 1, "paramet": 1, "9": 1, "still": 1, "support": [1, 2], "deprec": [1, 2], "pleas": [1, 2], "wa": 1, "becaus": 1, "guess": 1, "real": [1, 2], "alwai": 1, "fragil": 1, "broke": 1, "some": [1, 3], "legitim": 1, "usecas": 1, "have": [1, 2], "method": 1, "info": 1, "dictionari": 1, "account": 1, "limit": 1, "softwar": [1, 2], "achiev": 1, "might": 1, "correspond": 1, "dure": 1, "creation": 1, "There": [1, 2], "need": [1, 2], "check": 1, "realis": 1, "befor": [1, 2], "process": [1, 3], "come": 1, "send": [1, 2], "small": 1, "subset": 1, "cannot": 1, "queri": 1, "These": [1, 2], "store": 1, "thei": [1, 3], "were": 1, "user": [1, 2], "distinguish": 1, "them": 1, "retriev": 1, "prefix": 1, "yet": 1, "properti": 1, "deriv": 1, "directli": [1, 3], "obtain": 1, "kei": 1, "refer": [1, 3], "card_no": 1, "integ": [1, 3], "neg": 1, "indic": [1, 2], "device_no": 1, "subdevice_no": 1, "subdevic": 1, "state": 1, "access_typ": 1, "access": [1, 2], "type_nam": 1, "mode_nam": 1, "format_nam": 1, "format_descript": 1, "subformat_nam": 1, "subformat": 1, "subformat_descript": 1, "period_tim": 1, "durat": 1, "mu": 1, "period_s": 1, "buffer_tim": 1, "time": [1, 2, 3], "error": 1, "buffer_s": 1, "get_period": 1, "approx": 1, "rate_numden": 1, "numer": 1, "denomin": 1, "tupl": 1, "significant_bit": 1, "signific": [1, 3], "is_batch": 1, "doubl": 1, "boolean": 1, "true": 1, "is_block_transf": 1, "block": 1, "transfer": 1, "is_doubl": 1, "is_half_duplex": 1, "half": 1, "duplex": 1, "is_joint_duplex": 1, "joint": 1, "can_overrang": 1, "overrang": 1, "detect": 1, "can_mmap_sample_resolut": 1, "resol": 1, "mmap": 1, "can_paus": 1, "paus": 1, "can_resum": 1, "resum": 1, "can_sync_start": 1, "synchron": 1, "start": 1, "italic": 1, "summari": 1, "full": [1, 2], "document": 1, "relat": 1, "pass": 1, "instant": 1, "describ": 1, "after": 1, "pcmmode": 1, "One": 1, "pcm_async": 1, "cardnam": 1, "setchannel": 1, "nchannel": 1, "setrat": 1, "setformat": 1, "setperiods": 1, "librari": [1, 2], "otherwis": 1, "those": [1, 2], "pyalsaaudio": [1, 2], "dumpinfo": 1, "dump": 1, "stdout": 1, "retur": 1, "current": [1, 2, 3], "stream": 1, "one": [1, 2, 3], "pcm_state_open": 1, "happen": 1, "pcm_state_setup": 1, "drop": 1, "drain": [1, 3], "pcm_state_prepar": 1, "pcm_state_run": 1, "pcm_state_xrun": 1, "pcm_state_drain": 1, "pcm_state_paus": 1, "pcm_state_suspend": 1, "pcm_state_disconnect": 1, "read": [1, 3], "In": [1, 3], "until": 1, "length": 1, "where": 1, "frames": 1, "becom": 1, "last": 1, "case": 1, "an": [1, 3], "overrun": [1, 3], "epip": 1, "lost": 1, "even": [1, 2], "oper": [1, 2, 3], "itself": 1, "succeed": 1, "try": [1, 2], "write": [1, 3], "must": [1, 3], "multipl": 1, "exactli": [1, 3], "less": 1, "than": 1, "provid": [1, 2, 3], "playout": 1, "more": [1, 2], "written": 1, "kernel": [1, 2, 3], "enough": 1, "been": [1, 2], "allow": [1, 3], "immedi": 1, "zero": 1, "later": [1, 2], "complet": [1, 2, 3], "continu": 1, "afterward": 1, "discard": 1, "handl": [1, 2, 3], "enabl": 1, "stop": 1, "residu": 1, "all": [1, 2, 3], "pend": 1, "veri": [1, 2], "close": 1, "polldescriptor": 1, "descriptor": 1, "eventmask": 1, "wait": 1, "poll": 1, "compat": 1, "regist": 1, "__": 1, "set_tstamp_mod": 1, "pcm_tstamp_en": 1, "timestamp": 1, "pcm_tstamp_non": 1, "get_tstamp_mod": 1, "set_tstamp_typ": 1, "pcm_tstamp_type_gettimeofdai": 1, "pcm_tstamp_type_monoton": 1, "pcm_tstamp_type_monotonic_raw": 1, "get_tstamp_typ": 1, "htimestamp": 1, "second": [1, 3], "nanosecond": 1, "frames_available_in_buff": 1, "tstamp_typ": 1, "tabl": 1, "system": [1, 2, 3], "wide": 1, "realtim": 1, "clock": 1, "epoch": 1, "monoton": 1, "unspecifi": 1, "progress": 1, "ntp": 1, "tstamp_mod": 1, "No": [1, 2], "updat": 1, "everi": [1, 3], "posit": 1, "few": [1, 2], "hint": 1, "common": 1, "reason": 1, "problem": [1, 2], "match": 1, "too": 1, "underrun": [1, 3], "ugli": 1, "click": 1, "occur": [1, 3], "convers": 1, "much": 1, "your": [1, 2], "program": 1, "doe": [1, 3], "noth": [1, 3], "best": 1, "strategi": 1, "put": 1, "just": 1, "possibl": 1, "separ": 1, "thread": 1, "sole": 1, "task": 1, "out": [1, 3], "gui": 1, "howev": 1, "mai": [1, 2], "better": 1, "setup": [1, 2], "preload": 1, "coupl": 1, "timer": 1, "purpos": [1, 2], "avoid": 1, "doesn": 1, "t": [1, 2], "expir": 1, "api": [1, 2, 3], "find": [1, 2], "accummul": 1, "delai": 1, "th": 1, "timeout": 1, "slightli": 1, "accumul": 1, "quit": 1, "lot": [1, 3], "realli": 1, "add": 1, "extra": 1, "nessecari": 1, "master": 1, "id": 1, "specifi": 1, "manipul": [1, 2], "other": [1, 2, 3], "mono": [1, 3], "line": 1, "etc": [1, 3], "specif": [1, 2, 3], "mixerid": 1, "switchcap": 1, "switch": [1, 3], "mute": 1, "join": 1, "exclus": 1, "Not": [1, 3], "setrec": 1, "setmut": 1, "volumecap": 1, "volum": 1, "capabl": [1, 2], "volumn": 1, "getenum": 1, "enumer": 1, "item": 1, "my": [1, 2], "soundcard": [1, 2], "get": 1, "simpl": 1, "enum": 1, "mix": 1, "mic": 1, "item0": 1, "could": 1, "do": [1, 2], "import": [1, 3], "m": 1, "empti": 1, "setenum": 1, "getrang": 1, "unit": 1, "volume_units_raw": 1, "rang": [1, 3], "whose": 1, "determin": [1, 3], "relev": 1, "both": 1, "volume_units_percentag": 1, "volume_units_db": 1, "getvolum": 1, "element": 1, "setvolum": 1, "none": 1, "present": 1, "assum": 1, "independ": 1, "getmut": 1, "fail": [1, 2], "flag": 1, "getrec": 1, "handleev": 1, "acknowledg": 1, "event": [1, 3], "prevent": 1, "subsequ": 1, "again": 1, "rant": 1, "extrem": 1, "complic": 1, "hardli": 1, "implement": [1, 2], "simplifi": [1, 2], "wai": 1, "design": 1, "ve": 1, "had": 1, "choic": 1, "chosen": 1, "would": [1, 2], "reexpos": 1, "horribl": 1, "complex": 1, "ratio": 1, "underli": 1, "At": [1, 3], "least": [1, 2, 3], "easi": 1, "chois": 1, "someth": 1, "let": 1, "me": [1, 2], "know": 1, "so": [1, 2, 3], "incorpor": 1, "futur": 1, "affair": 1, "annoi": 1, "howto": 1, "net": 1, "somebodi": 1, "stai": 1, "unfortun": 1, "abl": 1, "creat": 1, "myself": 1, "pain": 1, "trial": 1, "except": 1, "accept": 1, "valid": 1, "player": 1, "wav": [1, 2], "run": 1, "raw": 1, "cd": [1, 3], "qualiti": 1, "filenam": [1, 2], "speak": [1, 2], "interrupt": [1, 2, 3], "ani": [1, 2, 3], "ctl": [1, 2], "back": [1, 2], "without": [1, 2], "look": [1, 2], "headphon": 1, "rear": 1, "pc": 1, "aux": 1, "With": 1, "singl": [1, 3], "61": 1, "two": [1, 2, 3], "Or": 1, "40": 1, "differ": [1, 2, 3], "author": 2, "casper": 2, "wilstrup": 2, "cwi": 2, "av": 2, "dk": 2, "lar": 2, "immisch": 2, "ibp": 2, "de": 2, "licens": 2, "under": 2, "psf": 2, "major": 2, "distribut": 2, "basic": 2, "anyth": 2, "wish": 2, "commerci": 2, "warranti": 2, "whatsoev": 2, "packag": 2, "wrapper": 2, "It": 2, "fairli": 2, "midi": 2, "sequenc": 2, "low": 2, "our": 2, "prioriti": 2, "volunt": 2, "welcom": 2, "github": 2, "issu": 2, "don": 2, "report": 2, "regard": 2, "sever": 2, "team": 2, "advanc": 2, "linux": 2, "architectur": 2, "logic": 2, "consist": [2, 3], "compon": 2, "driver": 2, "respons": 2, "physic": 2, "within": 2, "standard": 2, "5": [2, 3], "level": 2, "space": 2, "userspac": 2, "applic": [2, 3], "libasound": 2, "requir": [2, 3], "inform": 2, "about": 2, "project": 2, "homepag": 2, "http": 2, "www": 2, "org": 2, "older": 2, "oss": 2, "now": 2, "well": 2, "ossaudiodev": 2, "nativ": 2, "exist": 2, "includ": 2, "pyalsa": 2, "neither": 2, "seem": 2, "activ": 2, "develop": 2, "featur": 2, "wrote": 2, "fill": 2, "gap": 2, "long": 2, "term": [2, 3], "goal": 2, "unlik": 2, "own": 2, "difficult": 2, "work": 2, "greatli": 2, "appreci": 2, "link": 2, "alsasound": 2, "lib": 2, "header": 2, "compil": 2, "verifi": 2, "usr": 2, "similar": 2, "path": 2, "build": 2, "On": [2, 3], "debian": 2, "probabl": 2, "ubuntu": 2, "libasound2": 2, "dev": 2, "natur": 2, "proper": 2, "6": [2, 3], "patch": 2, "yourself": 2, "although": 2, "ship": 2, "execut": 2, "py": 2, "root": 2, "playwav": 2, "sndrpihifiberri": 2, "recordtest": 2, "playbacktest": 2, "minim": 2, "suit": 2, "depend": [2, 3], "familiar": 3, "whether": 3, "input": 3, "amplitud": 3, "certain": 3, "point": 3, "individu": 3, "necessari": 3, "taken": 3, "mani": 3, "precis": 3, "vari": 3, "music": 3, "dynam": 3, "between": 3, "quietest": 3, "loudest": 3, "signal": 3, "reproduc": 3, "per": 3, "simpli": 3, "we": 3, "re": 3, "six": 3, "48": 3, "flow": 3, "often": 3, "replac": 3, "consum": 3, "kb": 3, "64kbit": 3, "end": 3, "scale": 3, "4608": 3, "almost": 3, "mb": 3, "met": 3, "xrun": 3, "cpu": 3, "chunk": 3, "fragment": 3, "hold": 3, "trigger": 3, "caus": 3, "context": 3, "overhead": 3, "smaller": 3, "higher": 3, "resourc": 3, "usag": 3, "bigger": 3, "improv": 3, "resili": 3, "being": 3, "split": 3, "top": 3, "up": 3, "sooner": 3, "hand": 3, "increas": 3, "latenc": 3, "sent": 3, "audibl": 3, "similarli": 3, "trade": 3, "off": 3, "made": 3, "alsaaudio": 3, "onc": 3, "readi": 3}, "objects": {"": [[1, 0, 0, "-", "alsaaudio"]], "alsaaudio": [[1, 1, 1, "", "Mixer"], [1, 1, 1, "", "PCM"], [1, 3, 1, "", "asoundlib_version"], [1, 3, 1, "", "cards"], [1, 3, 1, "", "mixers"], [1, 3, 1, "", "pcms"]], "alsaaudio.Mixer": [[1, 2, 1, "", "cardname"], [1, 2, 1, "", "close"], [1, 2, 1, "", "getenum"], [1, 2, 1, "", "getmute"], [1, 2, 1, "", "getrange"], [1, 2, 1, "", "getrec"], [1, 2, 1, "", "getvolume"], [1, 2, 1, "", "handleevents"], [1, 2, 1, "", "mixer"], [1, 2, 1, "", "mixerid"], [1, 2, 1, "", "polldescriptors"], [1, 2, 1, "", "setenum"], [1, 2, 1, "", "setmute"], [1, 2, 1, "", "setrec"], [1, 2, 1, "", "setvolume"], [1, 2, 1, "", "switchcap"], [1, 2, 1, "", "volumecap"]], "alsaaudio.PCM": [[1, 2, 1, "", "cardname"], [1, 2, 1, "", "close"], [1, 2, 1, "", "drain"], [1, 2, 1, "", "drop"], [1, 2, 1, "", "dumpinfo"], [1, 2, 1, "", "get_tstamp_mode"], [1, 2, 1, "", "get_tstamp_type"], [1, 2, 1, "", "htimestamp"], [1, 2, 1, "id0", "info"], [1, 2, 1, "", "pause"], [1, 2, 1, "", "pcmmode"], [1, 2, 1, "", "pcmtype"], [1, 2, 1, "", "polldescriptors"], [1, 2, 1, "", "read"], [1, 2, 1, "", "set_tstamp_mode"], [1, 2, 1, "", "set_tstamp_type"], [1, 2, 1, "", "setchannels"], [1, 2, 1, "", "setformat"], [1, 2, 1, "", "setperiodsize"], [1, 2, 1, "", "setrate"], [1, 2, 1, "", "state"], [1, 2, 1, "", "write"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "function", "Python function"]}, "titleterms": {"alsaaudio": [0, 1], "document": 0, "content": 0, "download": 0, "github": 0, "indic": 0, "tabl": 0, "pcm": [1, 3], "object": 1, "mixer": 1, "exampl": 1, "playwav": 1, "py": 1, "recordtest": 1, "playbacktest": 1, "mixertest": 1, "introduct": 2, "abstract": 2, "what": 2, "i": 2, "alsa": 2, "python": 2, "instal": 2, "test": 2, "terminologi": 3, "concept": 3}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"alsaaudio documentation": [[0, "alsaaudio-documentation"]], "Contents:": [[0, null]], "Download": [[0, "download"]], "Github": [[0, "github"]], "Indices and tables": [[0, "indices-and-tables"]], "alsaaudio": [[1, "module-alsaaudio"]], "PCM Objects": [[1, "pcm-objects"]], "Mixer Objects": [[1, "mixer-objects"]], "Examples": [[1, "examples"]], "playwav.py": [[1, "playwav-py"]], "recordtest.py and playbacktest.py": [[1, "recordtest-py-and-playbacktest-py"]], "mixertest.py": [[1, "mixertest-py"]], "Introduction": [[2, "introduction"]], "Abstract": [[2, null]], "What is ALSA": [[2, "what-is-alsa"]], "ALSA and Python": [[2, "alsa-and-python"]], "Installation": [[2, "installation"]], "Testing": [[2, "testing"]], "PCM Terminology and Concepts": [[3, "pcm-terminology-and-concepts"]]}, "indexentries": {"mixer (class in alsaaudio)": [[1, "alsaaudio.Mixer"]], "pcm (class in alsaaudio)": [[1, "alsaaudio.PCM"]], "alsaaudio": [[1, "module-alsaaudio"]], "asoundlib_version() (in module alsaaudio)": [[1, "alsaaudio.asoundlib_version"]], "cardname() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.cardname"]], "cardname() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.cardname"]], "cards() (in module alsaaudio)": [[1, "alsaaudio.cards"]], "close() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.close"]], "close() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.close"]], "drain() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.drain"]], "drop() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.drop"]], "dumpinfo() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.dumpinfo"]], "get_tstamp_mode() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.get_tstamp_mode"]], "get_tstamp_type() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.get_tstamp_type"]], "getenum() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.getenum"]], "getmute() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.getmute"]], "getrange() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.getrange"]], "getrec() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.getrec"]], "getvolume() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.getvolume"]], "handleevents() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.handleevents"]], "htimestamp() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.htimestamp"]], "info() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.info"], [1, "id0"]], "mixer() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.mixer"]], "mixerid() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.mixerid"]], "mixers() (in module alsaaudio)": [[1, "alsaaudio.mixers"]], "module": [[1, "module-alsaaudio"]], "pause() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.pause"]], "pcmmode() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.pcmmode"]], "pcms() (in module alsaaudio)": [[1, "alsaaudio.pcms"]], "pcmtype() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.pcmtype"]], "polldescriptors() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.polldescriptors"]], "polldescriptors() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.polldescriptors"]], "read() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.read"]], "set_tstamp_mode() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.set_tstamp_mode"]], "set_tstamp_type() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.set_tstamp_type"]], "setchannels() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.setchannels"]], "setenum() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.setenum"]], "setformat() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.setformat"]], "setmute() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.setmute"]], "setperiodsize() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.setperiodsize"]], "setrate() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.setrate"]], "setrec() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.setrec"]], "setvolume() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.setvolume"]], "state() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.state"]], "switchcap() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.switchcap"]], "volumecap() (alsaaudio.mixer method)": [[1, "alsaaudio.Mixer.volumecap"]], "write() (alsaaudio.pcm method)": [[1, "alsaaudio.PCM.write"]]}}) \ No newline at end of file diff --git a/terminology.html b/terminology.html index e7ac084..71c8735 100644 --- a/terminology.html +++ b/terminology.html @@ -1,18 +1,17 @@ - + - + - PCM Terminology and Concepts — alsaaudio documentation 0.9.2 documentation + PCM Terminology and Concepts — alsaaudio documentation 0.10.0 documentation - - + @@ -34,7 +33,7 @@
      -

      PCM Terminology and Concepts

      +

      PCM Terminology and Concepts

      In order to use PCM devices it is useful to be familiar with some concepts and terminology.

      @@ -49,47 +48,53 @@

      PCM Terminology and Concepts -
      This is the size in bytes of each frame. This can vary a lot: if each sample
      -
      is 8 bits, and we’re handling mono sound, the frame size is one byte.

      Similarly in 6 channel audio with 64 bit floating point samples, the frame -size is 48 bytes

      -
      -
      -
      -

      +
      Frame size

      This is the size in bytes of each frame. This can vary a lot: if each sample +is 8 bits, and we’re handling mono sound, the frame size is one byte. +For six channel audio with 64 bit floating point samples, the frame size +is 48 bytes.

      Rate

      PCM sound consists of a flow of sound frames. The sound rate controls how often the current frame is replaced. For example, a rate of 8000 Hz means that a new frame is played or captured 8000 times per second.

      -
      Data rate

      This is the number of bytes, which must be recorded or provided per +

      Data rate

      This is the number of bytes which must be consumed or provided per second at a certain frame size and rate.

      8000 Hz mono sound with 8 bit (1 byte) samples has a data rate of 8000 * 1 * 1 = 8 kb/s or 64kbit/s. This is typically used for telephony.

      At the other end of the scale, 96000 Hz, 6 channel sound with 64 bit (8 bytes) samples has a data rate of 96000 * 6 * 8 = 4608 -kb/s (almost 5 MB sound data per second)

      +kb/s (almost 5 MB sound data per second).

      +

      If the data rate requirement is not met, an overrun (on capture) or +underrun (on playback) occurs; the term “xrun” is used to refer to +either event.

      -
      Period

      When the hardware processes data this is done in chunks of frames. The time -interval between each processing (A/D or D/A conversion) is known -as the period. -The size of the period has direct implication on the latency of the -sound input or output. For low-latency the period size should be -very small, while low CPU resource usage would usually demand -larger period sizes. With ALSA, the CPU utilization is not impacted -much by the period size, since the kernel layer buffers multiple -periods internally, so each period generates an interrupt and a -memory copy, but userspace can be slower and read or write multiple -periods at the same time.

      +

  • +
    +
    Period

    The CPU processes sample data in chunks of frames, so-called periods +(also called fragments by some systems). The operating system kernel’s +sample buffer must hold at least two periods (at any given time, one +is processed by the sound hardware, and one by the CPU).

    +

    The completion of a period triggers a CPU interrupt, which causes +processing and context switching overhead. Therefore, a smaller period +size causes higher CPU resource usage at a given data rate.

    +

    A bigger size of the buffer improves the system’s resilience to xruns. +The buffer being split into a bigger number of smaller periods also does +that, as it allows it to be drained / topped up sooner.

    +

    On the other hand, a bigger size of the buffer also increases the +playback latency, that is, the time it takes for a frame from being +sent out by the application to being actually audible.

    +

    Similarly, a bigger period size increases the capture latency.

    +

    The trade-off between latency, xrun resilience, and resource usage +must be made depending on the application.

    -
    Period size

    This is the size of each period in Hz. Not bytes, but Hz!. In -alsaaudio the period size is set directly, and it is +

    Period size

    This is the size of each period in frames. Not bytes, but frames! +In alsaaudio the period size is set directly, and it is therefore important to understand the significance of this number. If the period size is configured to for example 32, each write should contain exactly 32 frames of sound data, and each @@ -145,7 +150,7 @@

    Quick search

    - + @@ -162,8 +167,8 @@

    Quick search

    ©2017, Lars Immisch & Casper Wilstrup. | - Powered by Sphinx 4.5.0 - & Alabaster 0.7.12 + Powered by Sphinx 6.1.3 + & Alabaster 0.7.13 |

    Capability

    Description