Benjamin Matuszewski
email: benjamin.matuszewski@ircam.fr

The Web Audio API as a Standardized Interface Beyond Web Browsers

In this paper, the authors present two related libraries, web-audio-api-rs and nodeweb-audio-api, that provide a solution for using the Web Audio API outside the Web browsers. The first project is a low-level implementation of the Web Audio API written in the Rust language, and the second provides bindings of the core Rust library for the Node.js platform. The authors' approach here is to consider Web standards and specifications as tools for defining standardized APIs across different environments and languages, which they believe could benefit the audio community in a more general manner. Although such a proposition presents some portability limitations due to the differences between languages, the authors think it nevertheless opens up new possibilities in sharing documentation, resources, and components across a wide range of environments, platforms, and users. The paper first describes the general design and implementation of the authors' libraries. Then, it presents some benchmarks of these libraries against state-of-the-art implementation from Web browsers, and the performance improvements that have been made over the last year. Finally, it discusses the current known limitations of these libraries and proposes some directions for future work. The two projects are open-source, reasonably feature-complete, and ready to use in production applications.

INTRODUCTION

The Web Audio API first proposed by Chris Rogers in 2011 has received increasing attention by developers, artists, and researchers in the last decade. The possibility of doing advanced audio processing and synthesis natively on the Web platform has unfolded a number of novel possibilities in different application domains such as music performance and creation, gaming, or online conferencing. With its release as a W3C Recommendation in 2021 [START_REF] W3c | Web Audio API Specification[END_REF], the Web Audio API has reached a point at which its growing community of users, amount of documentation, and tutorials make it an interesting option for someone willing to develop an audio application.

Despite this increasing interest and the large possible application domains, the present authors believe that the adoption of the Web Audio API is limited by the sandboxed and constrained environments that are Web browsers. Their hypothesis is that with its stable and standardized specification, the Web Audio API could provide an interesting solution for audio application outside Web browsers. This approach is in line with recent trends and pervasiveness of using Web technologies and standards outside the Web. For example, the Node.js 1 and Deno2 efforts to implement standards such as JavaScript modules or the fetch API to improve interoperability with Web browsers, or the spread of the Electron3 project that proposes a way to build native applications from Web-based technologies, can be seen as going in a similar direction.

In this paper, the authors present two related projects and libraries that go in such direction and make use of Web standards as a way to model APIs outside Web browsers. web-audio-api-rs 4 is a low-level implementation of the Web Audio API written in the Rust programming language [START_REF] Matsakis | The Rust Language[END_REF][START_REF] Rottier | A Rust Implementation of the Web Audio API[END_REF] and node-web-audio-api a library that provides JavaScript bindings to the Rust implementation for the Node.js platform. 5

PAPERS THE WEB AUDIO API AS A STANDARDIZED INTERFACE BEYOND WEB BROWSERS

The main objectives for these libraries is to reach full compliance with the specification and, on its Rust version, deviate from it only in specific, justified, and predictable cases. On the Rust side, the authors aim at providing an API that is both easy to use when coming from a JavaScript background with only a few adaptations to the Rust coding style and specificities and, inversely, can leverage on existing JavaScript documentation and tutorials for Rust users. For the Node.js bindings, the goal is to provide a drop-in replacement to run existing Web Audio code and libraries in a Node.js context without any modifications.

As such, the authors believe their proposal can unfold interesting possibilities in several application domains. For example, it could open novel perspectives in several artistic areas such as distributed music systems [START_REF] Turchet | Internet of Musical Things: Vision and Challenges[END_REF][START_REF] Matuszewski | A Web-Based Framework for Distributed Music System Research and Creation[END_REF] or digital musical instruments creation [START_REF] Poupyrev | New Interfaces for Musical Expression[END_REF]. For start-ups and industries, it could provide a novel and standardized tool to support the path from prototyping to production (e.g., simple prototyping using JavaScript easily ported to Rust for performance and deployment) in different domains such as game development or sonification of embedded devices.

After a presentation of similar attempts in recent years (SEC. 1), the authors describe the general design and implementation of their libraries (SEC. 2). In SEC. 3, they present some benchmarks of their libraries against state-ofthe-art implementation from Web browsers, as well as the performance improvements that have been made over the last year. Finally, in SEC. 4, they discuss the current known limitations of the libraries and propose some directions for future work.

RELATED WORKS

Several attempts have been made over the years to implement the Web Audio API as an autonomous library to be used outside Web browsers. For example, the LabSound project [START_REF] Porcino | Graph-Based Audio Engine[END_REF] proposes an open-source C++ library originally forked from the Webkit implementation. Although the library appears to be maintained, the authors acknowledge in the presentation of the project that "LabSound has deliberately deviated from the spec for performance or API usability reasons," a standpoint which is "expected to continue into the future as new functionality is added to the engine." Derived from this project, the node-audio library [START_REF] Ramirez | Graph-Based Audio API for Node.js Based on LabSound and JUCE[END_REF] proposes Node.js bindings built on top of LabSound. However, the project is presented as in an "extremely experimental state" and did not receive any update for 5 years.

The web-audio-engine [START_REF] Mohayonao | Pure JS Implementation of the Web Audio API[END_REF] and web-audio-api [START_REF]Node.js Implementation of Web Audio API[END_REF] projects both propose an implementation of the Web Audio API written in pure JavaScript that could therefore be used within Node.js applications. However, these two libraries are obviously tied to the inherent limitations of the JavaScript language (e.g., single-thread, interpreted) and therefore cannot reach any serious performance comparison with low-level implementations. Furthermore, the first project has been archived by its author and no further support can be expected because the last published version of the second dates from 7 years ago.

Finally, the authors can cite the servo-media component [START_REF] Servo | Media[END_REF], created in the context of the Servo project backed-up by Mozilla, and also implemented in Rust. Although much larger in its scope, the library contained some promising steps toward a low-level implementation of the Web Audio API. However, it can be observed from the examples that the public Rust API differs in many regards from the JavaScript API, preventing reuse of acquired knowledge or to easily port code from one language to the other. Additionally, because the abandonment of the Servo project by Mozilla in August 2020, the library does not appear to be actively developed or maintained.

In the growing Rust ecosystem, a number of audio libraries with different scopes and goals have been proposed. For example, the dasp project [START_REF] Rustaudio | The Fundamentals for Digital Audio Signal Processing[END_REF] offers a number of components that provide low-level abstractions for working with digital audio signals. Inside this suite, the dasp-graph component aims at creating modular and dynamic audio graphs. However, the component is very general purpose and does not provide higher-level building blocks as defined in the Web Audio API.

On the other side of the spectrum, the Rodio project [START_REF] Rustaudio | Rust Playback Library[END_REF] proposes a high-level, beginner-friendly audio playback library. The library provides a number of audio sources and filters, which can be glued together with mixers, delays, crossfades, etc. It lacks, however, a few important building blocks for more advanced audio applications such as allowing multiple input streams per node or automation events. Additionally, it renders the audio output frame by frame, which may be a performance issue in constrained environments.

Inside this general frame, the authors think their proposal has the potential of filling several gaps. First, from a general Web Audio API perspective, it provides a solution decoupled from Web browsers, potentially widening its application areas and community of users. Second, from a Rust perspective, it proposes an intermediary and extensible solution that is both tied to an industry standard and is not yet available in the ecosystem. Finally, from a JavaScript perspective, it provides a new platform (i.e., Node.js) to deploy existing Web Audio code.

DESIGN AND IMPLEMENTATION

In this section, the authors describe the main design and implementation aspects of their project considering both the Rust and JavaScript versions. The choice of the Rust language for the core library has been motivated by several reasons. Primarily, Rust is a low-level, memory-efficient language such as C or C++. Hence, Rust features memory efficient primitives (float, double, atomic, referencecounted, etc.) and allows one to choose between stack and heap allocation and to define custom memory allocators. As such, the language provides all the characteristics requested to build real-time audio engines with predictive timing and high performance.

Additionally, compared to C/C++, Rust introduces the concept of data ownership, which prevents the entire class of race conditions and concurrency issues that may arise in multi-threaded execution. As such, it can guarantee that the concurrent execution of the control thread and render thread is free of data races. This analysis is performed at compile time, so there is no runtime cost of the memory safety rules. A drawback is that not all memory safe programs are allowed by the Rust compiler, forcing the developer to use sub-optimal solutions in specific cases (e.g., graph data structures). In these cases, the developer should benchmark the overhead and resort to unsafe operations when necessary. This has not been the case yet in the authors' library. Finally, the Rust ecosystem (e.g., compiler toolchain, dependency management, auto-generated documentation) is modern, easy-to-use, and beginner-friendly.

General Architecture

On multi-core processor systems, dynamic audio libraries typically split up work between a control thread and a render thread. This approach can be seen as a variation of the client/server architecture widely implemented in computer music-oriented languages and platforms [START_REF] Puckette | FTS: A Real-Time Monitor for Multiprocessor Music Synthesis[END_REF][START_REF] Déchelle | jMax: An Environment for Real-Time Musical Applications[END_REF][START_REF] Mccartney | Rethinking the Computer Music Language: SuperCollider[END_REF]. The Web Audio API, constrained also by the specifics of the JavaScript language, makes no exception and requires the implementation of this pattern. 6In such an architecture, the render thread has the sole responsibility of rendering the audio graph and shipping the samples to the operating system (OS) so they can be played by the hardware. This thread has, therefore, very hard real-time constraints: if it is unable to compute the next block of audio samples within its time budget, around 2.9 ms for blocks of 128 samples (the default render size of the Web Audio API) at 44.1 kHz, underruns will occur, and audible artifacts will be produced. On the other hand, the control thread is user-facing and orchestrates all changes to the audio graph. It mainly allows users to change the topology of the audio graph (i.e., adding and removing nodes, changing the connections between them) and to access and update parameters of the nodes. The authors' implementation indeed follows this model and uses lock-free message passing for cross-thread communication.

Each node of the audio graph is therefore composed of two complementary objects (see Fig. 1) that are always created as pairs:

• AudioNode: User-facing object that implements the AudioNode interface from the W3C spec. The AudioNode does not perform any audio processing but allows the user to change the audio graph and rendering by sending messages to its related AudioProcessor.

• AudioProcessor: Object that is placed on the render thread to produce the actual audio samples.

It cannot be directly manipulated by the user and relies on instructions received from its corresponding AudioNode to change its behavior.

The JS Interface as the API Model in Rust

The authors' Rust implementation follows the API defined by the W3C specification as closely as possible considering the specificities of the language. Indeed, some differences are impossible to avoid in translating an API targeted at JavaScript to Rust. For example, the most obvious deviation is that the authors chose to conform to the Rust coding style standard, which enforces the use of snake case for methods and CamelCase for enum variants.

Beyond this simple adaptation, an important set of differences lie in the implementation of object-oriented programming concepts that are very common in the specification but not supported by the language. First, Rust does not allow the authors to override property getters and setters. Therefore, instead of directly exposing attributes, 7the authors offer two methods [i.e., attribute() and set attribute()] as exemplified below:

Similarly, Rust does not provide any mechanism for method overloading. In such cases, rather than providing a single method with several Option parameters, the authors chose to expose several specialized methods. For example, AudioScheduledSourceNode::start([time]) is derived as start() and start at(time: f64).

Finally, Rust is strongly designed toward composition and does not provide any inheritance mechanism. Therefore, to mimic inheritance, the authors use Traits for parent/extendable interfaces such as AudioNode, Au-dioScheduledSourceNode, or BaseAudioContext and composition of struct for dictionaries such as the AudioNodeOptions interface.

The example code in Listing 1, which shows a scrubbing effect realized using a granular synthesis approach, illustrates what the authors think is a representative snippet of the resulting public Rust API. A given File is decoded into an AudioBuffer that is then consumed by several AudioBufferSourceNodes scheduled and configured to read the AudioBuffer back and forth at half speed.

Listing 1: Example code of a scrubbing effect realized with a granular synthesis approach written in Rust.

These differences prevent from dropping existing JavaScript source code into Rust and, thus, impede portability to some extent. However, the authors think the syntax and conceptual similarities can help developers to easily port their existing code to native in a very simple fashion. Although one could imagine creating some tool to automatically transpile JavaScript Web Audio code to Rust, providing such a tool would require substantial effort and is outside the scope of this project. The Node.js bindings described in SEC. 2.5 provide an intermediate solution to this particular issue.

AudioWorklet as the Internal Model

The public Rust API is de facto larger than the API defined by the specification given that the library must expose some of its internals to users to allow them to implement their own dedicated nodes. However, the design of the Au-dioProcessor interface is very much inspired by the AudioWorkletProcessor interface as defined in the specification [START_REF] Choi | AudioWorklet: The Future of Web Audio[END_REF]. Hence, AudioProcessors are stateful objects that will execute a callback of the following form on every render tick:

Here, inputs[n][m] and outputs[n][m] follow a planar layout where arrays of audio samples are stored in the mth channel of the nth input or output. The parameters object contains the computed values for each AudioParam of the AudioProcessor for this rendering quantum. The return value corresponds to the tail-Time behavior, which allows the AudioProcessor to be dropped by the AudioGraph when 1) its related Au-dioNode has been dropped itself, 2) it has finished its rendering, and 3) it has no input connections left.

The additional RenderScope argument is modeled after the specification of the AudioWorkletGlob-alScope. It contains the current time, sample frame, and sample rate, and in the future, it will allow processors to share data (such as wavetables or Fast Fourier Transform results) within the render thread.

The AudioRenderQuantum type used for inputs and outputs is a specialized container type that uses fixed-sized, reference-counted arrays with copy on write semantics. It allows for efficient implementation of upmixing and down-mixing, fan-in/out of channels, and, in a general way, moving input and output buffers around without making copies or allocating memory.

Control and Render Threads

Method calls on the audio contexts, audio nodes, and audio params that occur in the control thread, typically spin off a control message to be handled by the render thread. These methods, which operate synchronously and do not block, are therefore safe to use on a UI thread. Additionally, the concept of control thread itself is more abstract in this implementation because all AudioNodes are implemented in a thread-safe way.

The communication between the control thread and render thread is established through a single asynchronous communication channel called the control message queue. The queue is a first-in first-out queue where items are ordered by time of insertion, the oldest message being at the front of the queue. This single message bus ensures that updates made to the audio graph are applied in the right order in the render thread.

Render thread-wise, the authors' implementation does not directly interface with the system audio backend (e.g., ALSA, ASIO) but delegates this functionality to crossplatform audio libraries. Currently, the default audio middleware is cpal [START_REF] Rustaudio | Cross-Platform Audio I/O Library in Pure Rust[END_REF], but the authors also offer experimental support for cubeb [START_REF] Mozilla | A Cross-Platform Audio Library in Rust[END_REF]-a backend used by various programs such as high-profile console emulators, but mostly developed by Mozilla for Firefox-behind a compiler flag. Both libraries support a large range of audio backends so this library should work on a wide range of operating systems and hardware. The chosen audio backend will set up a real-time high priority OS thread to collect the audio samples. This is the thread in which all AudioProcessors are running. In a general manner, the entry point of an audio backend library is a callback that expects the authors to fill an array of float or integer interleaved audio samples (i.e., a FnMut(&mut [f32|u16|i16]) in Rust idiom). Although the desired size of the output array can be specified (e.g., 128 samples per channel in the Web Audio API specification), in practice, this value is not always available or allowed by the underlying system. In such a case, the authors still render the audio graph piecewise in blocks of 128 samples, maintaining the accuracy and regularity of the computed audio time, but perform internal buffering to align the buffer sizes. For example, if the audio library callback data size is 192, two buffers of size 128 will be rendered on one over two backend calls.

In the render thread, the AudioGraph is responsible to store the AudioProcessors and render them in the right order by performing a topological sort of the nodes as defined in the specification. 8 This algorithm ensures that when node A has an outgoing connection to node B, the processor of A is called before B. Therefore, when A has rendered, its resulting samples are copied and mixed appropriately to serve as input for processor B. The ordering is cleared and recomputed each time a node is added to the graph or when the connections between them are altered. Additionally, during this topological sort, a cycle detection is performed to mute every node that is part of the cycle unless a DelayNode is present.

Following both the specification and the JavaScript behavior, an AudioNode can go out of scope (i.e., to Drop in Rust idiom) in the control thread, while its processing counterpart continues to run inside the render thread. In such a case, the renderer is released only when it has finished processing (governed by the tailTime behavior). To implement this dynamic lifetime of the audio nodes, the AudioGraph, therefore, keeps track of the processors that have finished their rendering and consequently cleans up branches of the audio graph that will no longer emit output. On the contrary, if the AudioContext itself is dropped in the control thread, the corresponding render thread is immediately halted, and all resources are released.

Node.js Bindings

On top of the core Rust implementation, the authors also provide JavaScript bindings to web-audio-api-rs for usage within the Node.js platform. The package is available on the npm registry under the node-web-audio-api package name. This step backward to JavaScript from the Rust implementation opens a perspective the authors propose to call Isomorphic Web Audio. With this library, it is 8 https://www.w3.org/TR/webaudio/#rendering-loop. Note that there are subtle differences in the present authors' implementation because they are storing edge information in a different way. The resulting sort order conforms to the specification though.

indeed possible to write JavaScript Web Audio components that can run seamlessly in the browser or on the Node.js platform. As such, the authors believe this approach can be an interesting contribution in several areas such as distributed music systems using nano-computer without any screen (thus without Web browser) [START_REF] Matuszewski | Toward a Web of Audio Things[END_REF][START_REF] Matuszewski | A Web-Based Framework for Distributed Music System Research and Creation[END_REF] and more generally to the field of the Internet of Musical Things [START_REF] Turchet | Internet of Musical Things: Vision and Challenges[END_REF]. Additionally, the library opens the possibility for testing the whole implementation against the test suite from the web-platform-test project. 9The strategy used to build the library has been to generate most of the binding code directly from the Interface Description Language extracted from the specification. 10 This automatic approach has the additional benefit of testing and reinforcing the consistency of the Rust API. Furthermore, it allows to hide back the specificities of the Rust API described in SEC. 2.2 to expose an interface that is exactly similar to the one provided by Web browsers. As such, this new package potentially allows to reuse a whole set of existing higher-level libraries [START_REF] Schnell | Of Time Engines and Masters: An API for Scheduling and Synchronizing the Generation and Playback of Event Sequences and Media Streams for the Web Audio API[END_REF][START_REF] Mann | Interactive Music With Tone.js[END_REF] in a Node.js context and opens up possibilities of novel cross-environment workflows from prototyping to production.

At time of writing, while not completely up-to-date with the Rust implementation, the library already exposes all the nodes implemented on the Rust side and allowed to port an important subset of the existing Rust examples. Listing 2 shows a simple example of the usage of the library, i.e., an amplitude modulation synthesis with a periodic automation on the modulation frequency, running in a Node.js environment. It can be seen that, apart from the first import statement, which could be quite simply abstracted by a dedicated package, the script could perfectly run in a browser context without any further modifications.

Listing 2: Example code of an amplitude modulation synthesis realized with the JavaScript bindings in a Node.js context.

PAPERS THE WEB AUDIO API AS A STANDARDIZED INTERFACE BEYOND WEB BROWSERS

Fig. 2. Benchmarks run on a Macbook Pro 2020 (ARM) comparing the performances of the authors' library in its pure Rust version and with the Node.js bindings compared to the Firefox and Google Chrome Web browsers. Reported results are the speed-up compared to real time; therefore, higher values mean better performance. Note that the x axis is reported on a logarithmic scale.

PERFORMANCE

Audio processing systems typically face hard real-time constraints: when the production of new samples exceeds the time budget for a block (i.e., 128 samples for the Web Audio API), the rendering lags behind the actual playback, which produces discontinuities in the signal that are immediately perceived by listeners as "glitches." On the contrary, the more the overhead of the audio processing library is low, the more users can build complex audio graphs without running into issues. Performances of the render thread of any audio library are therefore a key aspect that must be carefully audited and optimized.

Benchmarks

To evaluate the current performances of this implementation (both in its raw Rust implementation and with the Node.js bindings) against state-of-the-art implementations from Web browsers, the authors chose to use the benchmarks developed by Adenot [START_REF] Adenot | Benchmarks for the WebAudio API[END_REF] to audit the performances of the Firefox Web browser. Although this specific test suite does not benchmark every single aspect of the Web Audio API and can therefore produce a biased picture, it still provides interesting highlights on key aspects of the implementation and allowed the authors to track their progress since the previously published results (cf. SEC. 3.2). The core principle of these benchmarks is to calculate an Au-dioBuffer (of generally 120 s) offline with different audio graphs and common synthesis methods. The time needed to calculate the buffer (i.e., between the start and end of the rendering) compared to the duration of the buffer therefore gives an estimation of the performances of the rendering against real time. The authors think this approach is particularly suited for benchmark comparisons between different languages because it cancels the JavaScript overhead in browsers and therefore only measures the audio processing time. As such, it allows to compare this implementation performance against the low-level C++ implementations from Web browsers.

The benchmarks have been run on two different computers: a MacBook Pro 2020 with an Apple M1 processor (ARM) and 8 GB of LPDDR4X-4,266 MHz RAM, and a MacBook Pro 2019 with a 2,3 GHz 8-Core Intel Core i9 processor and 16 GB of 2,400 MHz DDR4 RAM. For each tested platform, i.e., Google Chrome, Firefox, and the authors' Rust and Node.js libraries, the benchmarks were run five times with a dry compilation run for the Rust version and a full reload on a private browsing window between each run in the browsers. Reported results are the mean and standard deviation of these five executions and represent the speed-up compared to real time (i.e., bufferDuration/processingTime); hence, higher values mean better performance.

The ARM results presented in Fig. 2 (Intel results are reported in Fig. 4 in APPENDIX A.1 11 ) show that, except in some specific cases, this implementation compares quite well against mature Web browsers' implementations: around 1.3 times slower than Google Chrome and 1.8 times slower than Firefox for the Rust version on the ARM computer if all the benches are taken into account.

A more detailed analysis of the results show that the authors are noticeably behind only on very specific cases which gives some hints on where their future efforts should concentrate: 1) parsing graphs composed of many nodes, which is clearly visible in the "Granular synthesis" case, and 2) convolution reverberation, which is known as a very hard and specialized problem that will require important work. If these specific cases are removed, the comparison gets far better: around 1.1 times faster than Google Chrome and 1.5 times slower than Firefox, which the authors consider very promising, considering these implementations have been optimized for years.

Another point worth mentioning is that, as expected, the performances of the Node.js version are almost in line with the Rust ones, which confirms initial assumptions for benchmarking, i.e., cancellation of the JavaScript overhead. However, an important discrepancy can be noticed between the authors' libraries in the two cases that involve graphs composed of many nodes, i.e., Granular synthesis and Trigger oscillator with envelope. This difference tends to highlight an issue in this implementation that will require further investigation.

Optimizations

Important work has been done in the last year to improve the performances of the library (see Fig. 3 for ARM results; Intel results are reported in Fig. 5 in APPENDIX A.1). For this purpose, the authors implemented an important set of optimizations beyond the application of common practices for audio processing such as avoiding heap allocation, mutexes, and thread locks, or simple compiler optimizations. In this section, the authors describe three points that they consider the most interesting and representative.

First, results from Fig. 3 show that the Granular and Trigger oscillator with envelope benches have been improved by a factor of around 3. This gain in performance is primarily due to improvements in the representation of the graph itself and improvements made to the algorithm for its parsing. As discussed above, although encouraging, results from Fig. 2 show that this critical point is not yet satisfactory and will require further work.

Second, important work has been done on the processing of AudioParam. The authors consider this point worth mentioning because they implemented a strategy that, although compliant with the specification regarding audio rate and control rate parameters behavior, can be described as a generalization over these concepts. Indeed, in the current implementation, a-rate params produce a value for each sample of a quantum only when an automation is occurring and behave as a k-rate param the rest of the time, producing only one single value for the entire render quantum. Such a strategy allowed the implementation of a number of simple optimizations in many nodes. For example, a gain node linked to a mute button can simply act as a pass-through or produce a silent buffer, while still behaving normally when transitioning from 1 to 0 or inversely.

Finally, because of the planar channel layout required by the specification and described in SEC. 2.3, the authors revised their processors to ensure channels are accessed and written one by one to avoid jumps between different sections of memory at the sample level. In some nodes, e.g., AudioScheduledSourceNode or DelayNode, such an approach required to implement an additional loop dedicated to compute and store intermediate results (e.g., absolute position at the sub-sample level), which may seem surprising but actually led to better performances.

An untapped source of performance improvements are fast-math operations. These operations break IEEE compliance for float calculations, such as reordering of instructions or assuming only finite numbers exist. However they can enable great performance improvements, such as better vectorization of float buffer computations, which are utilized a lot in audio processing. In Rust, these fast math flags can be applied granularly (at the function level) but are unfortunately not available in the stable compiler toolchain yet. In the near future, the authors will experiment with the nightly compiler toolchain to evaluate the possible performance improvements and when possible, will backport some of the improvements to work in the stable channel. This can be done, for example, by unrolling certain loops by hand and making them suitable for 4-or 8-lane f32 vector operations.

DISCUSSION AND FUTURE WORK

With the recent addition to their implementation of the features "Access to a different output device" 12 and the AudioRenderCapacity13 interface, the authors are nearing feature completeness according to the specification. However, although preliminary work has been conducted to fully test their implementation against the Web Platform Test Suite, 14 the authors are conscious that a number of important points still needs to be tackled in order to provide a fully compliant and more efficient API.

PAPERS THE WEB AUDIO API AS A STANDARDIZED INTERFACE BEYOND WEB BROWSERS

Current Known Limitations

One important concept of the Web Audio API that is currently missing in the authors' implementation are asynchronous functions (i.e., methods that return a JavaScript Promise). The Rust equivalent of a function returning a Promise is an async function that landed in the core language in 2019 [START_REF]The Rust Release Team[END_REF] and opened the possibility for libraries that perform input/output to offer asynchronous versions of their functionality. Although the authors have already drafted an asynchronous version of some important methods (i.e., AudioContext.decodeAudioData, Of-flineAudioContext.startRendering, and Au-dioContext.resume), their implementation currently only exposes synchronous versions of the async functions in the specification. Although asynchronous APIs could be provided by spawning new threads to turn underlying synchronous APIs into asynchronous APIs, full asynchronous support is also dependent on downstream libraries (e.g., the media decoder) because they must support asynchronous execution before it can be used.

The Web Audio API is rather isolated from other Web standards, which makes it relatively simple to decouple it from the Web. However, it interfaces with few other Web standards that must be considered. Among them, the MediaStream15 and HTMLMediaElement16 interfaces are of great importance.

The MediaStream interface appears in the specification through the MediaStreamAudioSourceNode (input) and the MediaStreamAudioDestinationNode (output) interfaces and allows users to move audio data, respectively, into or out of the boundary of the audio context. These input/output possibilities are essential for building rich apps such as digital audio workstations, video conferencing, or online gaming. For now, the authors provide a minimal, spec-compliant implementation of the MediaStream that only allows audio tracks. Advanced features, such as solutions for clock drift of different media sources and sinks, or buffering and playback speed adjustments are not provided.

Likewise, the html <media> element, and its related HTMLMediaElement JavaScript representation, is an essential component of audio applications on the Web. It provides fetching of external resources, buffering, and different playback commands. The current implementation is very minimal because it only supports file-based media playback but, however, proposes a compliant interface: Besides these general and architectural issues, a few other limitations of this implementation at time of writing are worth mentioning. First, the PannerNode only supports mono input signal, multichannel input being downmixed to mono first. The PannerNode HRTF (head-related transfer function) database is relatively old, and the panning implementation does not perform any interpolation, which can produce audible artifacts for very fast-moving sound sources. Second, the ConvolverNode is limited to mono input as well. It implements a simple on-thread implementation of frequency-domain delay-lines, which is very inefficient and, therefore, only supports short impulse responses. Important work will need to be done to provide more efficient approaches such as hybrid direct form and multi-thread partitioned convolution [START_REF] Gardner | Efficient Convolution Without Input/Output Delay[END_REF][START_REF] Battenberg | Implementing Real-Time Partitioned Convolution Algorithms on Conventional Operating Systems[END_REF] and support larger impulse responses. Third, the OscillatorNode does not fully adhere to the specification: the built-in oscillators are not based on PeriodicWave and only apply rudimentary strategy to prevent aliasing (i.e., polyBLEP).

Extensibility

The question of extensibility is an important aspect that has been tackled in the specification with the legacy ScriptProcessorNode and more recently with the introduction of the AudioWorklet interface [START_REF] Choi | AudioWorklet: The Future of Web Audio[END_REF]. Such an interface is indeed required in JavaScript because of the particular nature of the language and of the necessity to be able to run arbitrary code in the high-priority audio thread. In a Rust context, this question is, however, posed differently because these limitations and constraints do not hold anymore.

Because the authors' implementation of audio processors closely resembles the signature of the AudioWorklet-Processor callback (see SEC. 2.4), they have decided so far to not implement the entirety of the AudioWorklet interface on the Rust side (e.g., MessagePort, etc.). Instead, the authors expose their AudioProcessor trait in the public Rust API library, and users are advised to use it in order to build custom audio nodes. However, regarding the Node.js version of the library, the question comes back in a similar way as within Web browsers. Therefore, in a future version of the library, the authors will consider implementing a compliant interface for AudioWorklet. Such addition would furthermore allow users to run existing Web Assembly [START_REF] Haas | Bringing the Web Up to Speed With WebAssembly[END_REF] modules in different environments and languages, opening new perspectives for community-built audio modules.

The ScriptProcessorNode, which, contrary to the AudioWorkletNode, runs the audio callbacks in the control thread and, as such, is considered flawed by the specification editors, poses a different question. Indeed, the authors consider that in specific situations, the benefits of using this node outweigh the complexity of setting up an AudioWorletNode and handling communication between threads. More precisely, the authors consider this node interesting if not used to produce audio samples but only as a way to access the audio stream, which is not feasible using the AnalyserNode, to control other processes (e.g., to implement an envelope follower). Additionally, it provides a simple way to introduce audio processing in pedagogical situations in which setting up an Au-dioWorkletNode would also be overwhelming. Hence,

Fig. 1 .

 1 Fig. 1. General architecture of the library, each component living in the control thread (audio context and audio nodes) has an associated counterpart living in the render thread (audio graph and audio processors).

Fig. 3 .

 3 Fig. 3. Normalized performance improvements against the previously published version-Macbook Book Pro 2020 (ARM).

PAPERS A. 1 Fig. 4 .

 14 Fig. 4. Benchmarks run on a Macbook Pro 2019 (Intel) comparing the performances of the library in its pure Rust version and with the Node.js bindings compared to the Firefox and Google Chrome Web browsers. Reported results are the speed-up compared to real time; therefore, higher values mean better performance. Note that the x axis is reported on a logarithmic scale.

Fig. 5 .

 5 Fig. 5. Normalized performance improvements against the previously published version-Macbook Book Pro 2019 (Intel).

https://nodejs.org/.

https://deno.land/.

https://www.electronjs.org/.

https://github.com/orottier/web-audio-api-rs.

https://github.com/ircam-ismm/node-web-audio-api.

J. Audio Eng. Soc., Vol. 71, No. 11, 2023 November

J. Audio Eng. Soc., Vol. 71, No. 11, 2023 November

https://www.w3.org/TR/2021/REC-webaudio-20210617/ #control-thread-and-rendering-thread.

Note that some attribute names such as type and loop are reserved keywords in Rust, and in these cases, the authors decided to append an underscore to the getter, e.g., Oscilla-torNode::type .

https://github.com/web-platform-tests/wpt.

https://webaudio.github.io/web-audio-api/#idl-index.

Note that for simplicity, the authors will only consider the ARM results in the current and following sections. Results from the Intel computer show a similar global picture. J. Audio Eng. Soc., Vol. 71, No. 11, 2023 November

https://github.com/WebAudio/web-audio-api/issues/2400.

https://github.com/WebAudio/web-audio-api/issues/2444.

https://github.com/b-ma/node-web-audio-api-wpt.

https://www.w3.org/TR/mediacapture-streams/.

https://www.w3.org/TR/2011/WD-html5-20110113/video. html#audio.

ACKNOWLEDGMENT

The authors would like to thank all their contributors and especially Jerboas86 for their precious contributions to the project. The authors would also like to thank their colleagues at IRCAM for their ideas and support. The project has received support from the DOTS research project funded by the French National Research Agency (ANR-22-CE33-0013-01).

PAPERS

the authors have decided to implement this node in the near future despite the fact that it is considered deprecated in the specification.

Performances

To audit and further improve the performances of their library, the authors have conducted preliminary work to adapt the test suite proposed by Spotify 17 to their Node.js implementation. 18 Because this project focuses on different aspects of the API compared to the suite used in SEC. 3.1, first results tend to show a complementary picture from the results reported above. Table 1 presents a small subset of the results obtained that the authors think are representative of these differences. Analyzing these results and improving the implementation accordingly will therefore require important future work.

CONCLUSION

In this paper, the authors have presented two relates libraries: web-audio-api-rs, a novel implementation of the Web Audio API specification implemented in the Rust language, and node-web-audio-api, a library that provides Node.js bindings to the core Rust library. First, the general design and implementation of the libraries were described. The authors then presented the current performance of the two libraries, compared to the state-of-the-art implementations provided by Web browsers, and the improvements that have been obtained compared to the previously published results. Finally, the authors discussed the current known limitations of their implementations and future directions for the development of the project.

Although still a work in progress, the two libraries expose a stabilized API, implement an important part of the specification, and provide reasonable performances. The authors consider that their approach of considering Web standards as a tool for defining standardized APIs across environments and languages could provide an interesting contribution to the audio community in a more general manner. Indeed, one could imagine implementing bindings 17 https://github.com/spotify/web-audio-bench. 18 https://github.com/b-ma/web-audio-bench.

on top of the core Rust library in other languages such as Python or Go, allowing users to take advantage of the standardized nature of the API and extensive documentation to build audio applications in their language of choice.

As open-source projects, the presented libraries are currently mainly developed and maintained by the two authors of the paper, with outside contributions in the form of pull requests and reported issues. To consolidate the project further and help to share development efforts, one of the authors' next objectives is now to develop a broader community of users and contributors.


Ramón Martí Solano

Isabel Celis Villalba

Proverbs in everyday speech versus frozen proverbs in dictionaries and texts: a corpus-based study

Keywords: Spanish proverbs, orally transmitted proverbs, variant forms, proverb modifications, semantic shift, corpus-based analysis

When proverbs are used in everyday speech, speakers tend to reproduce them with the same lexical and morphosyntactic structure and apply them to the same situations and contexts.

The aim of this paper is to highlight the differences between proverbs when used popularly in speech and their actual form and meaning in proverb dictionaries, collections or compilations, diachronic and synchronic corpora, literary quotations and the daily press.

Our research focuses on a small selection of traditional Spanish proverbs collected in Andalusia, southern Spain.

The selection includes, among others, the following proverbs: (a) No es señora quien lo es, sino quien lo sabe ser. [A lady is not she who is a lady but she who knows how to be one.] (b) No se puede luchar contra el destino, el que nace lechón muere cochino. [One cannot fight against destiny, he who is born a piglet dies a pig.] (c) Tiene el mal del milano, las patas malas y el pico sano. [He is like the sick kite, bad legs and a healthy beak.]

Sometimes proverbs are adapted according to the speaker and thus the canonical señor (gentleman) becomes señora (lady) as in (a). Other times, speakers add an extension to a single-sentence proverb which functions as a sort of down-to-earth rhymed illustration, as seen in the first part of (b). However, and most often, lexical synonymic or hyponymic substitution is to be found, as shown in (c) where patas malas (bad legs) is used instead of alas quebradas (broken wings) and pico (beak) is used instead of papo (crop)/ Preliminary results demonstrate that proverbs are not frozen or immutable multi-words units kept in dusty boxes in old museums but that they take a new life when used by speakers in everyday situations. Further research that would use the same methodological approach could serve the purpose of updating, or at least completing, the data found in dictionaries and proverb collections.

Introduction

The genesis of this research is a list of fifty orally transmitted proverbs within the same family in Andalusia, southern Spain (see appendix). Most of them are related to life conditions in a rural environment during Franco's dictatorship. At that time, censorship was imposed to artistic, literary and academic activities but it also reached people's everyday life. Some issues could not be discussed, at least in public. In this context, proverbs were widely used to provide "survival strategies" to the younger generation. This research work originated to pay homage to the Celis Villalba family for their paremiological inheritance and life lessons.

Sources of the research, selection of proverbs and method of analysis

The original list of fifty orally transmitted proverbs was randomly gathered out of memory. Some of them were commonly used but others were not or seemed to have some specific features or variations. For this piece of research, we used several sources. First, the corpora of the Royal Academy of the Spanish language, that is the Corpus diacrónico del español (CORDE), a diachronic corpus that comprises texts from the early times of the Spanish language up to 1975, the Corpus del español actual (CREA), a corpus of the last quarter of the 20 th century, and the Corpus del español del siglo XXI (CORPES XXI), a corpus of contemporary Spanish of the 21 st century. Then the orally transmitted proverbs and their potential canonical forms were checked in the proverb collection by Hernán Núñez published in 1555. After consulting the corpora of the Royal Spanish Academy, we drew up a shorter list (actually seven proverbs) with specific lexico-grammatical features, including different shades of meaning between the canonical form and the orally transmitted form of the proverbs in the original list. The final step was to do research on written sources where those proverbs appeared, mainly literary works and the press.

We completed our research by searching for the canonical forms in the database of the Refranero multilingüe (multilingual proverb database) from the Centro Virtual Cervantes from which their figurative sense was taken. The Refranero multilingüe (RM) was used as a source to start classifying the proverbs according to different criteria trying to focus on what we considered specific features of the orally transmitted proverbs in the original list. We realized that there were lexical and syntactic differences between proverbs in this list and their corresponding forms in the RM and even found that some of the orally transmitted forms provided an extension functioning as a rhymed illustration of the canonical form.

Depending on the information retrieved from these previous sources and with the aim of finding earlier examples we used the archives of the Hemeroteca digital (Digital Newspaper Library) of the National Library of Spain, Google Scholar, Google Books and Europresse, a database which gives access to thousands of newspapers and magazines in several languages, thus making it possible to compile specific journalistic corpora for a given language and a given period.

For each of the seven proverbs that will be discussed below we provide the literal translation into English, the context of use of the orally transmitted form, the figurative sense of the canonical form, an analysis of the linguistic changes observed and some recorded written examples from corpora. It should be pointed out that the forms that have been chosen for the titles of each of the following sections are the orally transmitted forms and not the canonical forms.

No es señora quien lo es, sino quien lo sabe ser.

The literal translation of this proverb is 'A lady is not she who is a lady but she who knows how to be one.' This orally transmitted form is generally used by women who think very high of themselves when referring to other women who, in their opinion, do not do so-called 'traditional women's chores'. The canonical form conveys a slightly different figurative sense that can be glossed as 'What makes people respectable is not their birth but the way they conduct themselves'.

The most outstanding difference between the orally transmitted form (henceforth OTF) and the canonical form (henceforth CF) is the semantic restriction of the OTF as it refers specifically to women and how they relate to each other.

All the examples found in corpora and other written records are in the masculine, that is they use señor instead of señora. The canonical form translates as 'A gentleman is not he who is born a gentleman but he who knows how to be one': Non es señor el que señor nace, sino el que lo sabe ser (Martín Caro y Cejudo, 1792) and No es señor quien señor nace sino quien sabe serlo [START_REF] Aguilera | Refranero panameño: contribución a la paremiología hispanoamericana[END_REF] 1 . There is also a variant form of the nominal constituent (caballero instead of señor, both of them meaning 'gentleman'), found in an 18 th -century proverb collection [START_REF] Sbarbi | El refranero general español: parte recopilado y parte compuesto[END_REF].

Only one example has been found in the corpora of the Royal Spanish Academy (1) and very few in the archives of the Hemeroteca digital, exactly five, of which three include the variant form noble (nobleman) [START_REF]No es señora quien lo es sino quien lo sabe ser[END_REF]. Example ( 1) is an extract of a comedy that illustrates the use of the canonical form in literature and which, following the CF, includes nacer (be born) and señor (gentleman) whereas in the OTF the verb is ser (to be) and the noun is señora (lady).

No se puede luchar contra el destino: el que nace lechón muere cochino.

The literal sense of this proverb is 'One cannot fight against destiny, he who is born a piglet dies a pig.' This OTF is used to express a reproof towards someone who recurrently behaves or acts in the same way. The canonical form in the RM, Quien nace lechón muere cochino, is registered with the following figurative sense: 'It is impossible to change one's nature when one has received it by genetic inheritance' 2 and does not include the rhymed introduction used in the OTF, No se puede luchar contra el destino (one cannot fight against destiny), which functions as a general maxim preceding the CF to provide a down-to-earth illustration of the proverb itself.

Only one example has been found in the corpora of the Royal Spanish Academy (3), a very recent use in literature, most interestingly with a positive connotation, whereas the idea of reproof prevails in all the other examples. Example (4) has been retrieved from Google Books and includes a variant form of the rhymed introduction of the OTF, es luchar contra el sino, the first line of a quatrain with a rhyme scheme ABBA. In the case of (5), found in the archives of the Hemeroteca Digital, it should be noted that the proverb is not only used in direct speech (signaled by the quotation marks) but is also preceded by como dirían en mi tierra (as they would say in my region), which reinforces the idea of its current used in the spoken language. This proverb follows the same paremiological pattern as other proverbs with the same meaning: quien negro nace, negro muere (he who is born a black man dies a black man); quien tronco nacio, tronco murió (he who was born physically disabled, dies physically disabled), quien asno nace, asno muere (o yace) (he who is born an ass, dies an ass); quien tuerto nace, tuerto se yace (he who is born a one-eyed man, dies a one-eyed man) (Lida 1958: 27). This pattern is very productive in Spanish and particularly in the different national varieties of the Spanish language as can be observed in the quotation below: Spanish zoonymic variants meaning "fate is unavoidable" are quoted by Arora (1998), like sp. el que nació para caballo ha de morir pastando *he who was born a horse, will die grazing; el que nace tatú muere cavando [Bol.] *he who was born a tatú (armadillo), he dies digging (Ibid.); quien nace lechón muere cochino *he who was born a sucker-pig dies as a swine (Mex.); […] (Pamies-Bertrán, 2012: 295)

A veces se besan manos que se quisieran ver cortás.

This OTF is used as a survival strategy, as a piece of advice given to someone in a lower rank when dealing with a superior. It translates literally as 'Sometimes one kisses hands that one would like to see cut off.' The figurative sense of the CF, Muchos besan manos que querrían ver cortadas (Hernán Núñez, 1555) or Muchos besan manos ke kerrían ver kemadas; o kortadas [START_REF] Correas | Vocabulario de refranes y frases proverbiales[END_REF]) can be glossed as 'Sometimes one has to make an effort to be dutiful and respectful to whom one despises.'

The most relevant feature of the OTF is the inclusion of the frequency adverb a veces (sometimes) that appears in initial position in place of the pronoun muchos (many people). This leads us to infer that the advice provided should not always be followed, but only when needs be. The use of the shortened form cortás, a dialectal truncated form of the standard past participle cortadas, is the reflection of a typical oral feature in the speech of Andalusian Spanish.

Contrary to the two previous proverbs, which only had one token in corpora, there are thirteen tokens of this proverb in CORDE although none in CREA or CORPES XXI, which accounts for the relative extent of use in the past and its decay in present-day Spanish.

Most of the examples are from the 16 th century and show different types of variations, however, example (6) is the only case in which the frequency adverb a veces is used, although not in initial position. As for example [START_REF]Tiene el mal del milano, las patas malas y el pico sano[END_REF], a later use of the proverb, it should be noted the use of the variant form quemadas (burnt) instead of cortadas (cut off) and the inclusion of the interpolated metalinguistic comment decía mi abuela (my grandmother used to say). ( 6) y que las mugeres puedan / tanto, que nos humillemos / a ellas y las amemos; / pero no por esso quedan / desculpadas, / antes muy más condenadas / con sus pliegues y doblezes; / manos se besan a vezes / que devrian ser cortadas (CORDE, Cristóbal de Castillejo, 1544, Diálogo de Mujeres) [START_REF]Tiene el mal del milano, las patas malas y el pico sano[END_REF] Es como lo dice Vuesa Señoría, contestó con desfachatez el imprudente barbero; y no ha sido el menor de mis sacrificios el aparecer favorito y paniaguado del Conde de la Gomera y de algunos de sus amigos. Manos besamos que quisiéramos ver quemadas, decía mi abuela, señor Visitador. (CORDE, José Milla y Vidaurre, 1867, El visitador)

Tiene el mal del milano, las patas malas y el pico sano.

This proverb, which has a second part with a parallel opposite symmetrical pattern, translates as 'He/she is like the sick kite, bad legs and a healthy beak.' This OTF is generally used as a reproof to someone who willingly accepts an invitation to eat but rejects a suggestion to work.

The CF, El mal del milano, las alas quebradas y el pico sano, has two distinct senses. On the one hand, it refers to people who being cowardly boast about their bravery (Diccionario de Autoridades). On the other hand, it can also refer to people who being healthy and with a good appetite, pretend to be sick (Suñé Benages 2008: 115).

The OTF features lexical variation if compared with the forms found in Marqués de Santillana 1454, Hernán Núñez 1555 and Correas 1627, all of which include papo (crop) instead of pico (beak). Although the use of papo was coeval with pico in the 16 th century, as observed in [START_REF]Cuando marzo mayea, mayo marcea[END_REF] and ( 9), the noun papo was more widely used than pico at that time.

Ten tokens of the proverb have been found in CORDE although none in CREA or CORPES XXI. It is important to point out that most of the cases that appear in the different corpora go back to the 16 th century and that there is no real synchronic canonical form one can refer to, hence the importance of the OTF under analysis. This is one of the proverbs found in the Diálogo de la lengua by Juan de Valdés (González Martín, 1997: 285), El mal del milano, el ala quebrada y el papo sano, at a time, the 16 th century, when proverbs were used as illustrations to teach specific grammatical features, in this case the use of the masculine determiner el and not the feminine la before a feminine noun, ala, for euphonic reasons.

Hay ojitos que se enamoran de legañas.

The literal translation of this proverb is 'There are little eyes that fall in love with eye mucus'. This causal contradictive proverb (Dundes 1981: 57) is used to pass a personal judgment on the members of a couple in which one is more virtuous than the other, to the eyes of the speaker. This proverb is not registered in the RM, so there is no synchronic canonical form but a diachronic one Ojos hay que de lagaña se pagan 3 (Hernán Núñez 1555, Pedro Vallés 1549) whose figurative sense can be glossed as 'Taste is not always governed by reason'.

Several lexico-grammatical changes can be observed if the OTF is compared with the CF.

First of all, the hyperbaton found both in the topic and in the comment of the CF (ojos hay instead of hay ojos and de lagaña se pagan instead of se pagan de lagaña) is absent in the OTF which, besides, uses the modern verb enamorarse instead of the dated pagarse and introduces the diminutive ojitos. This is the proverb that has the greatest number of tokens in corpora, 14 tokens in CORDE, but, as is practically the general case, none in CREA or in CORPES. The relative high frequency can probably be due to the fact that the first recorded written record is found in one of the most influential literary works in Spain together with Don Quixote, that is The Tragicomedy of Calisto and Melibea, known as La Celestina (10). The proverb is then used more than a century later, this time with the verb enamorarse, as in [START_REF]Hasta el 40 de mayo no te quites el sayo[END_REF] and [START_REF]A caballo regalado no hay que mirarle el diente[END_REF] and not with the former vern agradarse.

Por una vez que maté un gato, me llamaron matagatos.

This OTF, which translates as 'Once I killed a cat and, from then on, I was called the cat-killer', is a quite transparent proverb about someone's bad reputation. It should be noted that the verb in this proverb is in the first person singular and that is used by the speaker to justify an exceptional wrong behaviour or action when they are accused of doing it regularly.

The figurative sense of the CF, Por un perro que maté, mataperros me llamaron, can be glossed as 'Sometimes an isolated case is enough to give somebody a bad reputation.' (RM).

The main difference between the CF and the OTF is lexical: perro (dog) becomes gato (cat) and mataperros (dog-killer) becomes matagatos (cat-killer). There are, however, no notable differences from a semantic point of view.

No tokens of the OTF have been found in any of the three corpora of the Spanish Royal Academy. However, several examples of the CF, such as ( 13) and ( 14), have been retrieved from the Hemeroteca digital. Event though the use of perro is the general rule, one case of the use of gato has been found [START_REF]El ojo del amo engorda el caballo[END_REF]. 'Little olive eaten, little stone away' is the literal translation of this proverb, or otherwise stated, when one has finished eating an olive, one throws the stone away, which, obviously, seems the logical thing to do. The proverb suggests that once a question or a topic is over one should stop thinking or talking about it, especially if it has been problematic or painful and recommends a course of action by advising someone to move ahead in life putting difficulties aside. The OTF uses the diminutive of the two nominal constituents of the proverb, which means that aceituna (olive) becomes aceitunita (little olive) and hueso (stone) becomes huesecito (little stone).

As can be seen in [START_REF]No se puede luchar contra el destino, el que nace lechón muere cochino[END_REF], an example from Peru and the only one found in the corpora of the Royal Spanish Academy, it is the CF, without the diminutives, that is used. [START_REF]No se puede luchar contra el destino, el que nace lechón muere cochino[END_REF] El verdugo, comprendiendo la burla de estas palabras, le contestó: -Holgárame de no ser pagado, que la paga ha de ser tal, que después que concluya con estos compañeros, venga yo a hacer cabal la docena del fraile. Aceituna comida, hueso fuera. (CORDE, Ricardo Palma, 1877, Tradiciones peruanas, cuarta serie)

All the other examples, ( 16), ( 17) and ( 18), were found in the Hemeroteca digital, include one or two diminutive forms and come from the press form South-western Spain. As with (5), example ( 18) also shows the importance of using the press as a corpus since, in these two instances, either proverb is used in direct speech, which demonstrates the use of the proverbs in the contemporary spoken language. [START_REF][END_REF] No saben ná los alemanes... Han conseguido lo que siempre buscaron: tener a sus pies a toda la mano de obra que necesiten a precio de saldo. Deben su bienestar a que los demás países le compran sus medicamentos, coches, trenes, tanques y demás, pero "aceitunita comida, huesecito fuera". Two other pieces of evidence of the Andalusian origin of this OTF are its inclusion in Modismos comparativos de Andalucía (Comparative Idioms from Andalusia), in which the proverb appears as Aceituna comida, huesecito fuera (Antequera Luengo, 2007: 17), but also the fact that Aceituna comida, hueso fuera is one of the many proverbs collected from informers by the Spanish writer Fernán Caballero 4 when living in Andalusia (Jarilla Bravo, 2019: 178).

Conclusions

Orally transmitted proverbs should be used as a benchmark against canonical forms and other written forms as found in texts since a thorough description of a given paremiological unit should include all its variant forms and detailed information about nonstandard semantics and pragmatics.

The search for examples in corpora shows that some of them are either non-existent (Por una vez que maté un gato me llamaron matagatos) or nonce forms (No es señor quien señor nace sino quien sabe serlo, Quien nace lechón muere cochino, Aceituna comida, hueso fuera).

However, the daily press provides examples of actual uses of proverbs that account for the vitality of their variant forms both in spoken language (direct or indirect speech) and in specific regional contexts, which is extremely helpful for acknowledging orally transmitted forms not as nonce formations or deviations but as real variant forms.

Collecting the greatest number of examples is essential for research on the evolution of paremiological semantics. The diversity of contexts of use will allow the researcher to identify and check whether the semantic specificities of the orally transmitted form are reflected or not in recorded written sources.

Endnotes

1.

Even though two references are provided, in fact they can be subsumed to only one canonical form as the difference between the two (el que / quien) are exact grammatical equivalents (he who / who).

2.

The analogical equivalent proverb in English is "A leopard can't change its spots" (used to say that people cannot change their basic personalities, habits, etc.).

3.

The verb pagarse in the sixteenth century is used in the same sense as the verb enamorarse (to fall in love) in contemporary Spanish.

4.

Fernán Caballero was the pseudonym of Cecilia Böhl de Faber y Ruiz de Larrea, her real name.

( 1 )( 2 )

 12 PRÍNCIPE Id con Dios. / MÚSICO 1 El cielo dé a vuestra alteza, señor, un siglo de vida, amén. / PRÍNCIPE Id con Dios. / MÚSICO 1 ¡Qué gran valor! / MÚSICO 2 ¡Qué cordura! / MÚSICO 1 Octavio, ven. No es señor quien señor nace, sino quien lo sabe ser. (CORDE, Luis Vélez de Guevara, c. 1630, Reinar después de morir) Bienaventuradas las provincias que tienen autoridades de iniciativas propias, y bienaventurados los pueblos que saben cumplir una de las Obras de Misericordia, que no es noble quien noble nace, sino quien lo sabe ser; (El Globo, Madrid, 1875)

( 3 )

 3 No conocía otra vida. Nació en un palacio rodeado de comodidades y sirvientes y murió en otro sin que le faltara bienestar y asistentes. Porque el que nace lechón, muere cochino. (CORPES XXI, Nieves Concostrina, 2018, Pretérito imperfecto) (4) Es luchar contra el sino / Con que vienen al mundo ciertas gentes, / Querer hacerlas pulcras y decentes: / El que nace lechón muere cochino. ("El lavatorio del cerdo", 1861-62, Miguel Agustín Príncipe y Vidaud, Fábulas en verso castellano) (5) Para el portavoz adjunto del Grupo Parlamentario Popular, Luis Ramallo, "cada uno se retrata como es, y como dirían en mi tierra, el que nace lechón muere cochino". (El País, 12/04/1988)

( 8 )( 9 )

 89 Elicia. Matado sea tal garguero. Por ella se puede dezir, el mal del milano, las alas quebradas y el papo sano / Areusa. Y cómo se dirá con razón esso y más, pues con tal herida tiene tales alientos.(CORDE, Gaspar Gómez de Toledo, 1536, Tercera parte de la tragicomedia de Celestina) Dixo don Francisco Fenollet: Ximeno, por su mal conoce el ajeno. / Dixo Joan Fernandez: Don Francisco, vos no quereis acabar de conoscer ese milan; por él se dixo: El mal de milano, las alas quebradas y el pico sano.(CORDE, Luis Milán, 1561, El Cortesano)

( 10 )

 10 ¿A quién "gentil"? ¡Mal me haga Dios si ella lo es ni tiene parte dello, sino que hay ojos que de lagaña se agradan! Santiguarme quiero de tu necedad y poco conocimiento. (CORDE, Fernando de Rojas, 1499, La Celestina) (11) Rojas.-Ésa misma, pues tenía muy mala cara, era un poquita sucia y no sé si tuerta; y sobre todo, más vieja que el alcabala. / Sol.-Señor, ojos hay que de lagaña se enamoran. / Rojas.-Quien feo ama, hermoso le parece. (CORDE, Agustín de Rojas Villadrando, 1603, El viaje entretenido) (12) Vase Valenzuela y sale Gálvez. / Gálvez. ¡Que haya mujer de tan mal gusto! Por ésta se debió de decir que hay ojos que de legañas se enamoran. (CORDE, Anónimo, c. 1611, El hospital de los podridos)

( 13 )

 13 Pero esta ocurrencia no ha de ser causa de lo que vulgarmente se dice de "por una vez que maté un gato me pusieron mata-gatos" (El Eco del Comercio, Madrid, 22/05/1846) (14) -Si, si… buenas felpas me costaron tus torpezas. Parecia que de intento tropezabas siempre con rivales ó maridos… -Qué! señor, por una vez que maté un perro… Ya no os acordais de mis buenos servicios. (El Corresponsal, Madrid, 22/05/1843) Aceitunita comida, huesecito fuera.

(

  Diario de Huelva, 29/03/2014) (17) Antañazo era lo de aceitunita comida huesecito fuera, esto es lo que admite el estadio propio y de ahí no se puede pasar. Es más, entonces ni a soñar que la demanda fuese a acercarse a la oferta. (Diario de Sevilla, 13/07/2022) (18) "Aceitunita comida, huesecito tirado". Son las palabras de Joaquín Caparrós cuando se le pregunta por la planificación de un Sevilla que se encuentra ya en plena competición oficial. (El País, Sevilla, 03/08/2018)