## Yet Another (WA)SAPI Output Plugin for Winamp (YASAPI)

Copyright © 2015-2016 by Peter Belkner (http://home.snafu.de/pbelkner/)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

The "Yet Another (WA)SAPI Output Plugin for Winamp" (YASAPI) utilizes the "Windows Audio Session API" (WASAPI). WASAPI's exclusive mode for rendering audio is a native way on Windows to render audio undisturbed, similar to Steinberg's "Audio Stream Input/Output" (ASIO). The YASAPI output plugin may serve as a replacement for any other Winamp output plugin.

Home: |  | http://out-yasapi.sourceforge.net/
Project: |  | http://sourceforge.net/projects/out-yasapi/
Download: |  | http://sourceforge.net/projects/out-yasapi/files/out-yasapi/
WA Forum: |  | http://forums.winamp.com/showthread.php?t=380396

### Content

1. History
2. Introduction
3. Implementation
4. Configuration
5. Debug

### 1. History

2016-01-13 | 1.0.6 |

- Detect end of track by respective "isplaying" request.
- Fixed bug regarding synchronization of Share Mode and Strategy options.

2016-01-09 | 1.0.0 |

- Some minor code clean-up.
- Further development is stalled because according to the Winamp team they have developed a native WASAPI output plugin: "Benski has coded a new out_wasapi plug-in" (http://forums.winamp.com/showthread.php?p=3045974), "it'll probably be included with 5.8 beta" (http://forums.winamp.com/showthread.php?p=3045979).

2016-01-03 | 0.16.0 |

- Guarded against writing when paused.
- Stopping audio client when underflow.
- From the configuration dialog, dropped the device list page in favour of a combobox on top of the dialog.
- Slightly adapted default values.

2015-12-21 | 0.15.0 | Brought back, as an option, a call to IAudioClient::IsFormatSupported which is disabled by default.
2015-12-10 | 0.14.1 | Increased default ring buffer size to 2.5.
2015-12-08 | 0.14.0 |

- Introduced an (by default enabled) option "Write Block" that in case the plugin's "write" method delivers more data than actually could be written to the ring buffer it should block and wait until enough data are consumed from it rather then returning immediately.
- For automatic mode, removed restrictions for switching from exclusive to shared mode.

2015-12-06 | 0.12.0 | Fixed interplay with the "NotSo Fatso" input plugin.
2015-12-04 | 0.11.0 |

- Reorganized the configuration dialog:
  - Focused again on the most important two (per device) parameters "Mode" (share/exclusive) and "Strategy" (push/pull).
  - Duplicated those two parameters from the "Device Options" page to the dialog's top-region.
  - Moved the former top-region parameters to a new "General" tab-control page.
  - Added a "Store" button with similar functionality as the "OK" button except that it doesn't close the dialog.
- Fixed several bugs.

2015-11-29 | 0.10.0 |

- Reorganized configuration of device period.
- Added progess bars to the configuration dialog in order to visualize the load of the ring and the shared buffers.
- Added an option for dis-/enabling the visualization.
- Added an (experimental) function for balancing the shared buffer.
- Added some more tracing to the debug version.
- Split the verbose debugging into verbose level 1 ond and level 2 (even more verbose).

2015-11-23 | 0.9.1 |

- Added an option for configuring whether calculation of the buffer sizes should be based on the default or on the minimum device period as proposed by WASAPI. Made default device period the default. So long the calculation was silently based on the minimum device period.
- Added tooltips to the configuration dialog's controls.

2015-11-22 | 0.9.0 |

- Complete re-write based on a new architecture. The basic idea is to serialize all requests and dispatch them into just one worker thread. In particular the serialization takes into account asynchronous requests resulting from the WASAPI device.
- Round up ("ceil") the size of the ring buffer to the next multiple of Winamp's packet size (576 samples).
- Special treatment of double buffering, i.e. pull in exclusive mode.
- Additional options to configure the debug version.

Note: You should re-configure at least the buffer sizes. As a rule of thumb all buffer sizes should be 1.0 except the ring buffer's size which should be just a small amount greater then 1.0.
2015-11-02 | 0.8.3 |

- Improved thread synchronization during start-up.
- Fixed a bug regarding recovery from error `AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED` of the `IAudioClient::Initialize()` method.

2015-10-31 | 0.8.2 |

- Implemented recovery from error `AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED` of the `IAudioClient::Initialize()` method (cf. remarks section from MSDN documentation).
- Added support for KSAUDIO_SPEAKER_7POINT1.

2015-10-30 | 0.8.1 | New share mode "automatic" which is similar to exclusive except that it falls back to shared in case exclusive fails.
2015-10-29 | 0.8.0 |

- Improved synchronization with visualizations and video because of
  - corrected calculation of max latency and
  - corrected calculation of "written time".
- Dropped "written time" options.
- Dropped the call to IAudioClient::IsFormatSupported().
- New device specific options "Auto Convert PCM" and "SRC Default Quality". These Options are only available in shared mode. They correspond to the AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM and AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY flags, respectively, of the IAudioClient::Initialize() method (regarding the `AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY` flag cf. also here).

2015-10-26 | 0.7.1 |

- Automatic re-sampling in shared mode seems to work now.
- Added an "Exit Winamp" option to the error message dialog box.

2015-10-26 | 0.7.0 |

- Support for multiple devices.
- Configuration options per device.
- Various fixes.

Note: Prior configuration for the default device may be lost. Please re-configure.
2015-10-03 | 0.6.1 | Corrected a silly bug in testing for share mode.
2015-10-03 | 0.6.0 | Add AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM flag when in shared mode (doesn't have any effect on Vista).
2015-02-14 | 0.5.0 |

- Utilization of the IAudioClock interface instead of the GetTickCount() or the timeGetTime() functions for reporting the elapsed time to Winamp.
- Option for controlling whether "written time" should be calculated.

2015-01-30 | 0.4.0 |

- Option for treating mono as stero (default switched on).
- New default options for buffer configuration.
- Some fixes.

2015-01-25 | 0.3.0 |

- Support for pull strategy.
- Support for volume control.

2015-01-24 | 0.2.1 |

- Component Object Model (COM) error messages are displayed with the file and the line number where they occur.
- Compiled with shared `"MSVCR110.DLL"` (instead of static as before).

2015-01-24 | 0.2.0 |

- Improved configuration for buffer sizes.
- Provided a SSE2 version.
- Compiled with the C compiler from "Visual Studio 10 Express" (instead of "Visual Studio 9 Express" as before).

2015-01-23 | 0.1.0 | Initial release.

### 2. Introduction

According to Microsoft:

> The Core Audio APIs were introduced in Windows Vista. This is a new set of user-mode audio components provides client applications with improved audio capabilities. These capabilities include the following:
> - Low-latency, glitch-resilient audio streaming.
> - Improved reliability (many audio functions have moved from kernel mode to user mode).
> - Improved security (processing of protected audio content takes place in a secure, lower-privilege process).
> - Assignment of particular system-wide roles (console, multimedia, and communications) to individual audio devices.
> - Software abstraction of the audio endpoint devices (for example, speakers, headphones, and microphones) that the user manipulates directly.

> https://msdn.microsoft.com/en-us/library/windows/desktop/dd370784%28v=vs.85%29.aspx

Of special interest is that there is an exclusive mode for rendering audio, i.e. there is a mode where an application has exclusive access to the audio device without being disturbed by third parties.

The aim of the YASAPI plugin is to make the WASAPI exclusive mode for audio rendering available to the users of Winamp.

The name of the plugin was choosen because there are already at least two WASAPI output plugins for Winamp:

- Maiko WASAPI output plugin
- adionSoft Winamp WASAPI Output Plugin

### 3. Implementation

There are two sides the YASAPI plugin has to take into account:

- the WASAPI side, and
- the Winamp side.

The implementation on the WASAPI side follows along the lines of an example provided by Microsoft. The startegy shown in this example is not only applicable for shared mode streams but also for exclusive mode ones, i.e. not the share mode should be emphasized but what is known as the push model. There is also an example demonstrating the pull model in conjunction with the exclusive mode. In that sence there are four strategies:

- push exclusive,
- push shared,
- plull exclusive, and
- plull shared.

The YASAPI plugin implements the first two strategies, i.e. the ones based on the push model.

The push model, in principle, works as follows:

1. Query the size of the buffer shared with the audio device.
2. Fill in completety the buffer shared with the audio device.
3. Start playing.
4. Loop until the track is played:
   1. Sleep half of the time corresponding to the size of the buffer shared with the audio device.
   2. Into the buffer shared with the audio device, fill in the gap which was growing free by playing during sleep.
5. Sleep until the possibly remaining filled rest of the buffer shared with the audio device was played.
6. Stop playing.

But the YASAPI plugin not only has to take into account the WASAPI side (the loop consisting of sleeping and writing to the audio device) but also the Winamp side because Winamp provides the audio samples which should be played in an completely unpredictable way.

The YASAPI plugin decouples the two sides by means of a ring or circular buffer. That way,

- Winamp can luckily write to the ring buffer whenever it likes without caring about WASAPI, and
- WASAPI can luckily read from the ring buffer and write to the audio device wehenever it likes without caring about Winamp.

According to step 2 of the push model sketched above, it shoud become clear that the ring buffer should be at least as large (or larger) as the buffer the plugin's WASAPI component shares with the audio device.

### 4. Configuration

The YASAPI plugin comes with a configuration dialog which is described in the following. The dialog's top region presents the two most important parameters "Mode" (exclusive or share) and "Strategy" (push or pull)

Below those two parameters you find a tab-control consisting of four pages,

- a page for setting general (i.e. non device dependent) parameters,
- a page for choosing the device, and
- two pages for setting per device parameters.

The tab-control's first page looks as follows:

It let's you configure

- whether mono should be treated as stereo (i.e. the one mono channel should be duplicated),
- whether Winamp's volume control should be enabled, and
- whether the IAudioClock interface (WASAPI) or the GetTickCount function (System) should be used for synchronizing with Winamp.

On the next page there are the following per device options:

- the share mode, either exlusive, shared or automatic (automatic is similar to exclusive, except in case exclusive fails it falls back to shared), in case shared or automatic mode is choosen
  - whether the audio should be automatically re-sampled,
  - whether a more accurate re-sampling algorithmen should be applied, and finally
- the strategy, either push or pull.

On the final page you can configure the following per device buffer sizes:

- the duration of the buffer shared with the audio device (device period),
- the size of the ring buffer which should be a (small) multiple of the buffer the plugin's WASAPI component shares with the audio device, and
- the number of samples which should be available in the ring buffer before playing starts.

From the above sketch of the push model it shold be clear that the following relation holds (which is enforced by the configuration dialog):

> minimum size of the buffer shared with the device (provided by WASAPI) <= size of buffer shared with the device <= number of samples in the ring buffer before start playing <= size of ring buffer

As a rule of thumb all buffer sizes should be 1.0 except the ring buffer's size which should be just a small amount greater then 1.0.

Please note that no option takes effect before hitting the OK button.

### 5. Debug

In case something went wrong you may be interested in some more information. In order to utilize this there is a debug version of the plugin (distinguished by a lower case "d" at the and of the name, i.e. `out_yasapid.dll`) available from the download site.

Do the following:

1. Close Winamp.
2. Copy `"out_yasapi-debug.dll"` to Winamp's `"Plugin"` folder.
3. Start Winamp.
4. A console window should pop up tracing the initialiazation of the debug YASAPI plugin.
5. From Winamps's preferences dialog choose `"out_yasapi-debug.dll"` as output plugin.
6. When playing tracks in Winamp, the debug YASAPI plugin traces initialization and cleanup of each track.
7. When shutting down Winamp, the cleanup of the YASAPI debug plugin is traced.
8. After closing Winamp, the console window remains visible for another 5 s before vanishing.

The debug console.

You can get rid of the debug console by choosing the respective "Console" option from the debug YASAPI plugin's configuration dialog:

The following debug options can be configured:

- whether the debug console is switched Off or on and displaying a trace in Default or Verbose mode, and
- how long closing the debug console should be delayed from closing Winamp.