This commit is contained in:
chanweehewsonos
2025-09-10 13:40:11 +08:00
parent 3a3ee352a3
commit 2f26b992a2
1625 changed files with 656665 additions and 0 deletions

BIN
G-Audio/g-audio-main.zip Normal file

Binary file not shown.

44
G-Audio/g-audio-main/.gitattributes vendored Normal file
View File

@@ -0,0 +1,44 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
# Taken from https://github.com/Danimoth/gitattributes/blob/master/Common.gitattributes
# (note binary is a macro for -text -diff)
# Graphics
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.tif binary
*.tiff binary
*.ico binary
*.svg binary
*.eps binary
# LabVIEW
# Forcibly treat the bitfile as binary, otherwise GitHub sees the XML header and treats it as text.
*.lvbitx binary
# Treat the following XML type files as binary - text based diffing and merging can break them otherwise.
# See the section titled Managing the Project File in Source Code Control of this white paper: http://www.ni.com/white-paper/4114/en/
*.lvproj binary
*.lvlib binary
*.lvclass binary
*.xctl binary
*.lvsc binary

59
G-Audio/g-audio-main/.gitignore vendored Normal file
View File

@@ -0,0 +1,59 @@
# =========================
# Project Specific
# =========================
Post Install
# =========================
# LabVIEW Files
# =========================
# Metadata
*.aliases
*.lvlps
# Builds
[Bb]uilds/
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows shortcuts
*.lnk

View File

@@ -0,0 +1,193 @@
# Building and Packaging G-Audio
## Development Environment
The OS and software version selection is dependent on the versions supported by LabVIEW 2020, which is the LabVIEW version used to develop G-Audio. All development is done in virtual machines, except for Raspberry Pi which is on a physical Raspberry Pi 3B+.
OS | LV2020 Compatible Version | Link
---|---------------------------|------
Windows | Windows 8.1, 10 | [Compatibility table]( https://www.ni.com/en-us/support/documentation/compatibility/17/labview-and-microsoft-windows-compatibility.html)
macOS | macOS 10.14, 10.15 | [Compatibility table]( https://www.ni.com/en-us/support/documentation/compatibility/18/labview-and-macos-compatibility.html)
Linux | OpenSUSE 15.0, 15.1; CentOS 7, 8; RHEL 7, 8 | [Compatibility table]( https://www.ni.com/en-us/support/documentation/compatibility/20/labview-and-linux-os-compatibility.html)
Virtualization uses VMWare Player 16 patched with [Auto-Unlocker](https://github.com/paolo-projects/auto-unlocker/releases).
### Windows 10 VM
This is the primary dev environment.
Software | Links | Notes
---------|-------|------
LabVIEW 2020 Community edition for Windows (32-bit) | [Download](https://www.ni.com/en-us/support/downloads/software-products/download.labview.html#343639) |
Visual Studio 2019 Community edition | [Download](https://visualstudio.microsoft.com/vs/older-downloads/#visual-studio-2019-and-other-products) |
VIPM 2020.3 (build 2540) | [Download](https://www.vipm.io/desktop/installer/vipm-20.3.2540-windows-setup.exe/) | Don't use 2021, it has a build bug when parsing a VI in the LINX toolkit.
### macOS 10.14 VM
macOS ISO available on [archive.org](https://archive.org/details/macos-collection).
Software | Links | Notes
--------------|-------|-------
LabVIEW 2020 SP1 Community edition for macOS (64-bit) | [Download](https://www.ni.com/en-us/support/downloads/software-products/download.labview.html#370210) |
Xcode 11.3.1 | [Download](https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_11.3.1/Xcode_11.3.1.xip) | A comprehensive list of Xcode versions can be found on [xcodereleases.com](https://xcodereleases.com/)
VIPM 2020.3 (build 2540) | [Download](https://www.vipm.io/desktop/installer/vipm-20.3.2540-mac.zip/) |
### CentOS 8 VM
CentOS 8 is no longer supported by the maintainers, but is supported by LabVIEW 2020. After installing it, run the following commands to ensure the `yum` package manager can see the correct repos.
```
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
```
Software | Links | Notes
--------------|-------|-------
LabVIEW 2020 SP1 Community edition for Linux (64-bit) | [Download](https://www.ni.com/en-us/support/downloads/software-products/download.labview.html#370209) | The community edition ISO includes the pro LabVIEW version, no activation required. It isn't installed by the install script, but can be installed manually.
VIPM 2017.0 (build 2018) | [Download](https://www.vipm.io/desktop/installer/vipm-17.0.2018-linux.tar.gz/) | See below for installation notes.
#### Running VIPM on Linux
This was surprisingly hard. The Linux dev environment was originally OpenSUSE. After a series of issues getting VIPM to successfully launch, it then simply would not connect to LabVIEW. The OS was then changed to CentOS 8 which works with VIPM thanks to the help of [James McNally's post](https://forums.vipm.io/topic/2988-vipm-2017-on-centos-8/) on the VIPM forum.
1. Install support for the 32 bit LabVIEW RTE on 64 bit by running the following:
```
su
yum update libstdc++
yum install glibc.i686 libstdc++.i686 libXinerama.i686 libGL.so.1
```
2. Extract the VIPM tar.gz file, then edit `LabVIEW2015SP1RTE_Linux/INSTALL`. Find the line which begins with *RPMOPT* and add `--nodigest` at the end of the string. Save and close the file.
3. Follow the installation instructions in `instructions.txt` in the root of the VIPM archive.
4. To run VIPM, run the commands:
```
xhost si:localuser:root
su
cd /usr/local/JKI/VIPM
./vipm
```
VIPM should successfully launch, but may not be able to start LabVIEW 2020 Community edition, instead prompting with the activation dialog. This is due to LabVIEW only being activated under the user account, and not the root account which VIPM is required to run under. Attempting to activate LabVIEW under the root account then fails, as Firefox refuses to run as root user.
The workaround is to extract the LabVIEW pro / full rpm file from the ISO.
```
sudo rpm -i labview-2020-profull-exe-20.5.0.49152-0+f0.x86_64.rpm
```
### Raspberry Pi
Software | Links | Notes
---------|-------|------
Raspberry Pi OS | [Download](https://www.raspberrypi.com/software/operating-systems/#raspberry-pi-os-32-bit) | Desktop or Lite version
LINX library | [Download](https://www.vipm.io/package/ni_labview_linx_toolkit/) | This is already included with the community editions of LabVIEW. Use the *Tools > MakerHub > LINX > LINX Target Configuration...* wizard to install LINX to the Raspberry Pi.
ALSA and build packages | | See instructions below.
#### Package installation
SSH to the Raspberry Pi after installing the LINX environment, then enter the following commands to install the packages required for playing audio and building the G-Audio library.
```
sudo schroot -r -c lv
opkg update
opkg install alsa-lib
opkg install packagegroup-core-buildessential
opkg install --force-depends libc6-dev
opkg install --force-depends libgcc-s-dev
opkg install libstdc++-staticdev
opkg install git
opkg install alsa-lib-dev
exit
```
## Building the Shared Library
### Windows
Open the solution located at `src\C++\g_audio.sln`, then perform a batch build of both 32-bit and 64-bit releases. The resulting `g_audio_32.dll` and `g_audio_64.dll` files will be copied to `src\LabVIEW\G-Audio\lib\`.
### macOS
Open the Xcode project file location at `src/C++/xcode/g_audio_64.xcodeproj`. Build the library (hit build and run, or command+B). The resulting `g_audio_64.framework` library will be copied to `src/LabVIEW/G-Audio/lib/` with the following script:
```
cd $BUILT_PRODUCTS_DIR
rm -f g_audio_64.framework.zip
zip --symlinks -r g_audio_64.framework.zip g_audio_64.framework
cp -R g_audio_64.framework $PROJECT_DIR/../../LabVIEW/G-Audio/lib/
mv g_audio_64.framework.zip $PROJECT_DIR/../../LabVIEW/G-Audio/lib/
```
Note a zip file of the framework will also be created, reserving the symlinks within the framework folder. This zip file is included as part of the VIPM package, and is extracted during the VIPM package post installation.
### Linux
Change directory to `src/C++`, then run `chmod 755 make.sh; ./make.sh`. The resulting `g_audio_64.so` file will be copied to `src/LabVIEW/G-Audio/lib/`. The contents of make.sh are below:
```
#!/bin/bash
OUTPUT_PATH=../LabVIEW/G-Audio/lib
mkdir -p $OUTPUT_PATH
g++ -shared -fPIC -o g_audio_64.so *.cpp -lm -lpthread -ldl -O3
mv g_audio_64.so $OUTPUT_PATH
```
### Raspberry Pi
Ensure the Raspberry Pi has the necessary packages installed (alsa-lib, etc). SSH to the Pi, then issue the following commands to download the source code and build it.
```
sudo schroot -r -c lv
git clone https://github.com/dataflowg/g-audio
cd g-audio/src/C++
chmod 755 make_linx.sh
./make_linx.sh
exit
```
The resulting `g_audio_32.so` library will be placed in `/usr/lib` within the chroot (`/srv/chroot/labview/usr/lib`). This file should then be copied from the Pi and placed in `src\LabVIEW\G-Audio\lib\LINX` on the dev VM.
The contents of `make_linx.sh` are below:
```
#!/bin/bash
OUTPUT_PATH=/usr/lib
g++ -shared -fPIC -o g_audio_32.so *.cpp -lm -lpthread -ldl -std=c++11 -mfpu=neon -mfloat-abi=softfp -O3
mv g_audio_32.so $OUTPUT_PATH
```
## Packaging For VIPM
The packaging process for VIPM requires multiple steps to deal with issues relating to the combination of operating system targets and malleable VIs.
1. Open the VIPM build spec from `src\LabVIEW\VIPM\G-Audio.vipb`
2. Set the version number, then create the build.
3. Once the build has completed, open and run `src\LabVIEW\VIPM\Generate Post-Install.vi`. Point it to the newly created `.vip` file. This VI will then create a zip file in `src\LabVIEW\Post Install` containing the original versions of all the VIs and VIMs found in the VIPM package.
4. With the G-Audio build spec still open in VIPM, refresh the file list in Source File Settings. Set the version number back to the previously set value then build the package again, overwriting the existing package. This second rebuild is required to include the newly created zip file of original source VIs.
In theory the above could be performed using VIPM's packaging VIs, but they don't allow setting the major version to zero, while the user interface does. Once G-Audio reaches version 1.0 maybe this process can be revisited.
### Why so many steps?
Each *Call Library Function Node* (CLFN) in G-Audio is configured to call a library named `g_audio_*.*`. When search for the library, LabVIEW will automatically replace the two asterisks with the target bitness (32 or 64), and the OS specific library extension (dll, framework, or so). The final set of library names is below:
OS | Bitness | Library Name
---|---------|-------------
Windows | 32 | g_audio_32.dll
Windows | 64 | g_audio_64.dll
macOS | 64 | g_audio_64.framework
Linux | 64 | g_audio_64.so
Raspberry Pi | 32 | g_audio_32.so
When VIPM builds a package, it will replace the wildcards in the CLFN path with the host bitness and library type. When the package is installed on a target with a different bitness or OS, the VIs will be broken. See [this VIPM KB article](https://support.vipm.io/hc/en-us/articles/360053941572-VI-Package-Builder-removes-cross-platform-wildcards-from-Call-Library-Function-nodes-during-the-build-process) for more info.
The suggested workaround is to include a post-install script which updates all of the CLFN paths with the original wildcards. This works for VIs and top level malleable VIs, but does not work for malleable VIs on the block diagram. These malleable VIs are saved by LabVIEW as an instance VI within the calling VI. [Additional scripting](https://forums.vipm.io/topic/2427-call-library-function-node-32-and-64-bit/?do=findComment&comment=10107) is required to recursively identify instance VIs and update the CLFN paths. This works, but is incredibly slow.
Rather than trying to find and undo all of the CLFN path changes during the post-install stage, the G-Audio package includes a copy of the original, unmodified VIs along with the modified versions. After the modified versions are installed, a zip containing the original versions is extracted straight over the top of everything. Much faster and less error prone than the scripting approach.

View File

@@ -0,0 +1,67 @@
# G-Audio Release History
### v0.4.0 - 2022-07-12
* Raspberry Pi / LINX support
* Support for reading metadata tags (ID3v2, ID3v1, Vorbis Comments, RIFF INFO)
* Support for reading embedded artwork
* Advanced device configuration (exclusive mode, period size, num periods)
* Device volume adjustment (feature request #13)
* Get the configuration settings of a configured device (compare requested config vs actual config)
* Query detailed device info (default device, native sample rates, native channels, native formats)
* Warn of duplicate device config
* Update miniaudio (fixes #10)
* Fix memory leak when using UTF-16 converted file name
* [VIPM] Reduced package installation time
* [VIPM] Fix install error 5000 under macOS (#15)
##### New APIs
* `Get Audio File Tags.vi`
* `Set Audio Device Volume.vi`
* `Get Audio Device Volume.vi`
* `Get Audio Device Configuration.vi`
##### API Changes
* `Configure Audio Device.vi`:
* Added `Audio Device Advanced Config.ctl` input
* Added `Audio Device Config.ctl` and `Audio Device Advanced Config.ctl` outputs which contain the device's actual configuration, and can differ from the requested configuration
* Exclusive Mode flag moved from `Audio Device Config.ctl` to `Audio Device Advanced Config.ctl`
* `Query Audio Devices.vi` returns additional device info (default device, native sample rates, native channels, native formats)
### v0.3.1 - 2021-12-17
* Fix broken example VIs when VIPM package installed to LabVIEW 64-bit (issue #12)
### v0.3.0 - 2021-11-09
* Multi-channel audio mixer
* Loopback audio capture (WASAPI only)
* Sample pad & music visualizer examples
* Fix malleable VI broken wires (issue #4)
* Fix mp3 info memory error (issue #8)
* Upmix / downmix audio data to match audio device (issue #9)
* Auto cleanup audio devices on VI abort
### v0.2.1 - 2021-09-23
* Added `Get Audio File Position.vi` (issue #2)
* Codec detection based on file signature (issue #3)
* UTF-8 strings can be used as the path when opening files
* LabVIEW's unicode support treats strings as UTF-16 LE, so will require a conversion
* Automatically start audio device during playback and capture (issue #7)
* Fix misc. malleable VI issues (issue #4, #6)
##### API Changes
* Removed *Codec* input from `Open Audio File Read.vi`, `Quick Load Audio File.vi`, `Get Audio File Info.vi`
* `Open Audio File Read.vi`, `Quick Load Audio File.vi`, `Get Audio File Info.vi` are now polymorphic, accepting path type or string type as the Path input to support UTF-8 string paths
### v0.2.0 - 2021-09-05
* Playback and capture
### v0.1.0 - 2021-07-16
* Initial release

View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View File

@@ -0,0 +1,217 @@
# G-Audio
<p align="center">
<img width="300" height="115" src="images/g-audio-logo.png">
</p>
<p align="center">
A cross-platform LabVIEW library for audio device playback and capture, and for reading and writing audio files.
</p>
<p align="center">
<a href="https://www.vipm.io/package/dataflow_g_lib_g_audio/"> <img src="https://www.vipm.io/package/dataflow_g_lib_g_audio/badge.svg?metric=installs"></a> <a href="https://www.vipm.io/package/dataflow_g_lib_g_audio/"><img src="https://www.vipm.io/package/dataflow_g_lib_g_audio/badge.svg?metric=stars"></a>
</p>
<p align="center">
<a href="#whats-new">What's New?</a> -
<a href="#features">Features</a> -
<a href="#installation">Installation</a> -
<a href="#usage">Usage</a> -
<a href="#building">Building</a> -
<a href="#comparison">Comparison</a> -
<a href="#license">License</a> -
<a href="#acknowledgments">Acknowledgments</a>
</p>
## <a id="whats-new"></a>What's New?
* Raspberry Pi / LINX support!
* See the [Installation](#installation) section to get started.
* Support for reading metadata tags (ID3v2, ID3v1, Vorbis Comments, RIFF INFO)
* Support for reading embedded artwork
* Advanced device configuration options
* Misc. bug fixes
## <a id="features"></a>Features
* Support for audio playback and capture, including loopback capture
* Playback and capture using selectable backends (WASAPI, DirectSound, Core Audio, PulseAudio, ALSA, etc)
* Multi-channel audio mixer
* Read MP3, FLAC, Ogg Vorbis, and WAV formats
* Read metadata tags (ID3v2, ID3v1, Vorbis Comments, RIFF INFO) and embedded artwork
* Write WAV format (PCM and IEEE Float, with Sony Wave64 support for large files)
* Unicode path support (UTF-8) and unicode tag support
* Cross-platform (Windows, macOS, Linux, Raspberry Pi / LINX), 32-bit and 64-bit
* Simple to use API
![The G-Audio library API](images/g-audio-palettes.png?raw=true "The G-Audio library API")
## <a id="installation"></a>Installation
G-Audio is published on [vipm.io](https://www.vipm.io/package/dataflow_g_lib_g_audio/), and can be installed using VI Package Manager (VIPM). The packages are also available as [github releases](https://github.com/dataflowg/g-audio/releases) and can be installed manually using VIPM.
* **[macOS and Linux]** It's recommended to restart LabVIEW after installing the package via VIPM.
* **[macOS 10.14 and newer]** LabVIEW will require permission to access recording devices when performing audio capture. Make sure to enable this in the Security & Privacy settings. See [instructions here](https://support.apple.com/guide/mac-help/control-access-to-the-microphone-on-mac-mchla1b1e1fe/mac) on how to enable this setting.
If you want to include the library directly in your project, download or clone the repo and place the [G-Audio folder](https://github.com/dataflowg/g-audio/tree/main/src/LabVIEW/G-Audio) in your source directory, then add `G-Audio.lvlib` to your LabVIEW project.
* **[macOS]** Before adding the library to the project, extract `g_audio_64.framework.zip` located in `src/LabVIEW/G-Audio/lib/`.
### Raspberry Pi / LINX Installation
Before beginning, ensure your board has the LINX toolkit installed and SSH is enabled, and G-Audio has been installed on the host computer.
#### 1. Install ALSA to chroot
SSH into the LINX target (using PuTTy or similar) and run the commands:
```
sudo schroot -r -c lv
opkg update
opkg install alsa-lib
exit
```
#### 2. Copy `g_audio_32.so` to the target
*Note: This library has been compiled for armv7a processors. Other architectures may need to build the library before it can be used. See the [Building](#building) section.*
SCP / SFTP to the LINX target (using WinSCP or similar) and copy the library file located in `<vi.lib>\Dataflow_G\G-Audio\lib\LINX\g_audio_32.so` to the `/srv/chroot/labview/usr/lib` folder.
Alternatively, SSH to the LINX target and download the library direct from github:
```
cd /srv/chroot/labview/usr/lib
wget https://github.com/dataflowg/g-audio/raw/main/src/LabVIEW/G-Audio/lib/LINX/g_audio_32.so
```
#### 3. Make some noise!
Copy some audio files to your device using SCP or SFTP and place them in `/home/pi` or your preferred location. Create a LabVIEW project, add your LINX target, then the examples in the Add-ons >> G-Audio >> Examples >> LINX palette.
If you need to adjust the volume output, SSH into the LINX target and run `alsamixer`. Press F6, then select the physical audio device (not Default). Use the up and down arrow keys to adjust the volume, or use numbers 1-9 to set the volume in 10% increments. Press Esc to save and exit the mixer.
## <a id="usage"></a>Usage
See the example VIs in [Examples](src/LabVIEW/G-Audio/Examples) to write, read, playback, and capture audio files.
Unit tests are included and can be run individually, or with the [AST Unit Tester](https://www.autosofttech.net/documents/ast-unit-tester).
* **[macOS 10.14 and newer]** LabVIEW will require permission to access recording devices when performing audio capture. Make sure to enable this in the Security & Privacy settings. See [instructions here](https://support.apple.com/guide/mac-help/control-access-to-the-microphone-on-mac-mchla1b1e1fe/mac) on how to enable this setting.
### Supported Data Types
The `Playback Audio`, `Capture Audio`, `Audio File Read`, and `Audio File Write` VIs are malleable, and accept waveform arrays, waveforms, 2D arrays, and 1D arrays with types U8, I16, I32, SGL, and DBL (20 combinations in total). All audio data is processed in its native format, and then converted to the requested format if necessary. For WAV and FLAC files, any conversions are considered lossy, so check the file format before loading to ensure everything is lossless.
![Supported data types](images/g-audio-data-types.png?raw=true "Supported data types")
#### Malleable VIs and broken wires
If a malleable VI has broken wire inputs and errors about unsupported types, even though the type is supported, try hold Ctrl and click the run arrow. This will force LabVIEW to recompile the VI, and should hopefully fix those broken wires.
### Supported Metadata Tags
G-Audio supports reading ID3v2 and ID3v1 tags from MP3 files, Vorbis Comments from FLAC and Ogg Vorbis files, and RIFF INFO data from WAV files. All tag data is returned as an array of `Field` \ `Value` clusters from `Read Audio File Tags.vi`. The text encoding of `Value` can be specified to support tags containing unicode (note the `Field` text is always ASCII). Depending on the tag format, `Field` is named based on the tag (in the case of Vorbis Comments and ID3v2 `TXXX` fields), or mapped to a commonly named field. The table below shows the mapping between a common Field name and various tags.
Field | Description | ID3v2 | ID3v1 | RIFF INFO
------------|-----------------------------------------|-----------------------------|---------------|-----------
TITLE | The title of the track. | `TIT2`, `TT2` | Title | `INAM`
ARTIST | The track artist. | `TPE1`, `TP1` | Artist | `IART`
ALBUM | The album title. | `TALB`, `TAL` | Album | `IPRD`
ALBUMARTIST | The album artist. | `TPE2`, `TP2` | :x: | :x:
GENRE | The track's genre. | `TCON`, `TCO` | Genre ID | `IGNR`
DATE | The release date, typically the year. | `TYER`, `TYE` | Year | `ICRD`
TRACKNUMBER | The track's number in an album. | `TRCK`, `TRK` (**nn** / NN) | Comment[29] | `ITRK`
TRACKTOTAL | The total number of tracks in an album. | `TRCK`, `TRK` (nn / **NN**) | :x: | :x:
DISCNUMBER | The disc number within an album. | `TPOS`, `TPA` (**nn** / NN) | :x: | :x:
DISCTOTAL | The total number of discs in an album. | `TPOS`, `TPA` (nn / **NN**) | :x: | :x:
BPM | Beats Per Minute of the track. | `TBPM`, `TBP` | :x: | :x:
COMMENT | Notes and comments on the track. | `COMM`, `COM` | Comment[0-27] | `ICMT`
The field / tag mapping is based on the [Tag Mapping article](https://wiki.hydrogenaud.io/index.php?title=Tag_Mapping) on the hydrogenaudio wiki.
## <a id="building"></a>Building
Detailed build instructions can be found in [BUILDING.md](BUILDING.md), and covers development environment configuration, compilation details for each target, and VIPM packaging process.
Under Windows, Microsoft Visual Studio Community 2019 is used to compile and test the DLL called by LabVIEW.
Under macOS, Xcode 11.3.1 is used to compile the shared framework.
Under Linux, run the `make.sh` script to compile the shared object library, or manually compile with the command `g++ -shared -fPIC -o g_audio_64.so *.cpp -lm -lpthread -ldl -O3`.
Under Raspberry Pi / LINX, run the following commands from SSH:
```
sudo schroot -r -c lv
opkg update
opkg install packagegroup-core-buildessential
opkg install --force-depends libc6-dev
opkg install --force-depends libgcc-s-dev
opkg install libstdc++-staticdev
opkg install git
opkg install alsa-lib-dev
git clone https://github.com/dataflowg/g-audio
cd g-audio/src/C++
g++ -shared -fPIC -o g_audio_32.so *.cpp -lm -lpthread -ldl -std=c++11 -mfpu=neon -mfloat-abi=softfp -O3
cp g_audio_32.so /usr/lib
exit
```
## <a id="comparison"></a>Comparison
### Audio Playback & Capture
Feature | G-Audio | [LabVIEW Sound](https://zone.ni.com/reference/en-XX/help/371361R-01/lvconcepts/soundvis/) | [WaveIO](https://www.zeitnitz.eu/scms/waveio)
------------------------------|---------------------|-------------------------|--------------
Selectable backend | :heavy_check_mark: | :x: | :heavy_check_mark: (WASAPI, WinMM, ASIO)
Cross-platform | :heavy_check_mark: | :heavy_check_mark:¹ | :x: (Windows only)
Runtime device enumeration | :heavy_check_mark: | :x:² | :heavy_check_mark:
Audio device playback | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
Audio device capture | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
¹ *The backend for Linux is OSS, which was deprecated in Linux kernel version 2.5 in favor of ALSA. OSS support is not included out-of-the-box by any of the Linux distributions supported by LabVIEW 2020.*
² *LabVIEW Sound only enumerates devices when lvsound2.dll is loaded, and can't detect newly added or removed devices unless the entire library is unloaded and loaded again. See [this idea exchange entry](https://forums.ni.com/t5/LabVIEW-Idea-Exchange/Update-the-lvsound2-library-Sound-Input-Sound-Output-VIs-to/idi-p/2049098?profile.language=en) for details.*
### Audio Files
Feature | G-Audio | [LabVIEW Sound](https://zone.ni.com/reference/en-XX/help/371361R-01/lvconcepts/soundvis/) | [LabVIEW Audio DataPlugin](https://www.ni.com/example/25044/en/)
-----------------------------|---------------------|---------------------|-------------------------
Read WAV (PCM) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
Read WAV (IEEE Float) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
Read MP3 | :heavy_check_mark: | :x: | :heavy_check_mark:
Sample Accurate MP3 Length? | :heavy_check_mark: | - | :x:
Read FLAC | :heavy_check_mark: | :x: | :x:
Read Ogg Vorbis | :heavy_check_mark: | :x: | :x:
Read WMA | :x: | :x: | :heavy_check_mark:
Read metadata tags | :heavy_check_mark: | :x: | :x:
Read embedded artwork | :heavy_check_mark: | :x: | :x:
Write WAV (PCM) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
Write WAV (IEEE Float) | :heavy_check_mark: | :heavy_check_mark:¹ | :heavy_check_mark:¹
Write WAV (64-bit Float) | :heavy_check_mark: | :x: | :x:
Write Non-WAV formats | :x: | :x: | :x:
Large file support (>2GB) | :heavy_check_mark:² | :x: | :x:
Unicode paths | :heavy_check_mark:³ | :x: | :x:
Cross-platform | :heavy_check_mark: | :heavy_check_mark:⁴ | :x: (Windows only)
¹ *While LabVIEW Sound and LabVIEW Audio DataPlugin both support writing IEEE Float WAV files, writing the file and then reading it back shows they are **not** lossless. Both the read and write functions appear to be lossy (a file written by LV Sound and read with G-Audio will not be equal to the original data, as will a file written by G-Audio and read by LV Sound). dr_wav's (and by extension, G-Audio's) IEEE Float WAV write and read functions are lossless.*
² *64-bit version of LabVIEW required.*
³ *The path must be a UTF-8 encoded string (not path type) when passed to the Path input of the audio file functions. LabVIEW's file dialog and path controls don't support unicode, so getting the UTF-8 path into LabVIEW will require additional effort. String controls do support unicode with the `UseUnicode=TRUE` flag in **labview.ini** but are encoded as UTF-16 LE, so will require conversion to UTF-8 before use with G-Audio.*
*While LabVIEW Sound is cross-platform, testing under macOS and Linux shows writing 32-bit IEEE Float is unsupported.*
## Playback and Capture Buffering
The underlying mechanism for playback and capture is a callback made from the backend, where it requests the next block of audio data to be sent to the audio device, or the next available block read from the audio device.
The diagram below shows the audio data flow during playback. The function `Playback Audio.vim` and the backend callback run asynchronously. The ring buffer sits between the two, and keeps track of the next block of audio to be read (by the callback) and written (from LabVIEW). It's critical sufficient audio data is written to the ring buffer during playback, and read from the buffer during capture, to ensure there are no audio glitches.
Definitions used when referring to the diagram:
Term | Definition
-------|--------
Sample | Single unit of audio data, typically an I16 or SGL
Frame | Group of samples equal to number of channels
Period | 10ms of audio data (sample rate / 100). Typically 441 or 480 frames.
![The G-Audio library API](images/playback.png?raw=true "The G-Audio library API")
The *period* size should be regarded as the minimum buffer size when configuring the audio device. Note that the number of frames requested in the callback routine isn't necessarily fixed, and can be larger than a single *period*.
## <a id="license"></a>License
This library is built using public domain audio decoders and libraries. As such, this library is also made available in the public domain. See [LICENSE](LICENSE) for details.
## <a id="acknowledgments"></a>Acknowledgments
This library uses the following public domain libraries. Massive thanks to these authors.
Library | Author | Public Domain License
--------|--------|----------------------
[miniaudio](https://github.com/mackron/miniaudio) | David Reid | [Unlicense / MIT0](https://github.com/mackron/miniaudio/blob/master/LICENSE)
[dr_flac.h](https://github.com/mackron/dr_libs) | David Reid | [Unlicense / MIT0](https://github.com/mackron/dr_libs/blob/master/LICENSE)
[dr_wav.h](https://github.com/mackron/dr_libs) | David Reid | [Unlicense / MIT0](https://github.com/mackron/dr_libs/blob/master/LICENSE)
[minimp3](https://github.com/lieff/minimp3) | lieff | [CC0](https://github.com/lieff/minimp3/blob/master/LICENSE)
[stb_image.h](https://github.com/nothings/stb) | Sean Barrett | [Unlicense / MIT](https://github.com/nothings/stb/blob/master/LICENSE)
[stb_vorbis.c](https://github.com/nothings/stb) | Sean Barrett | [Unlicense / MIT](https://github.com/nothings/stb/blob/master/LICENSE)
[id3tag.h](https://github.com/mattiasgustavsson/i-love-music/tree/main/source/libs) | Mattias Gustavsson | [Unlicense / MIT](https://github.com/mattiasgustavsson/i-love-music/blob/main/LICENSE)
[thread.h](https://github.com/mattiasgustavsson/libs) | Mattias Gustavsson | [Unlicense / MIT](https://github.com/mattiasgustavsson/libs/blob/main/thread.h)
[base64](https://github.com/badzong/base64) | Manuel Badzong | [Unlicense](https://github.com/badzong/base64/blob/master/LICENSE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1300"
height="500"
viewBox="0 0 343.95833 132.29167"
version="1.1"
id="svg8"
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
sodipodi:docname="g-audio-logo.svg"
inkscape:export-filename="C:\github\dataflowg\g-audio\g-audio-logo.png"
inkscape:export-xdpi="22.15"
inkscape:export-ydpi="22.15">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="795.16116"
inkscape:cy="48.864992"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
transform="translate(39.687504,29.236465)"
id="g851">
<rect
style="fill:#ffffff;stroke:none;stroke-width:0.253365"
id="rect843"
width="343.95834"
height="132.29167"
x="-39.687504"
y="-29.236465"
rx="19.860098"
ry="18.469206" />
<g
transform="matrix(8.2859266,0,0,8.28553,-223.51367,-749.34997)"
id="g859">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5833px;line-height:1.25;font-family:'Segoe Script';-inkscape-font-specification:'Segoe Script';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
x="26.458334"
y="98.368309"
id="text12"><tspan
sodipodi:role="line"
id="tspan10"
x="26.458334"
y="98.368309"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Segoe Script';-inkscape-font-specification:'Segoe Script';fill:#ffcc00;fill-opacity:1;stroke-width:0.264583">G</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:7.53472px;line-height:1.25;font-family:sans-serif;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.188368"
x="34.812569"
y="97.375008"
id="text839"><tspan
sodipodi:role="line"
id="tspan837"
x="34.812569"
y="97.375008"
style="stroke-width:0.188368">-Audio</tspan></text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

353
G-Audio/g-audio-main/src/C++/.gitignore vendored Normal file
View File

@@ -0,0 +1,353 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# zig tool
zig/
zig-cache/

View File

@@ -0,0 +1,48 @@
========================================================================
DYNAMIC LINK LIBRARY : g_audio Project Overview
========================================================================
AppWizard has created this g_audio DLL for you.
This file contains a summary of what you will find in each of the files that
make up your g_audio application.
g_audio.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
g_audio.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
g_audio.cpp
This is the main DLL source file.
When created, this DLL does not export any symbols. As a result, it
will not produce a .lib file when it is built. If you wish this project
to be a project dependency of some other project, you will either need to
add code to export some symbols from the DLL so that an export library
will be produced, or you can set the Ignore Input Library property to Yes
on the General propert page of the Linker folder in the project's Property
Pages dialog box.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named g_audio.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,325 @@
/*
* Written by Manuel Badzong. If you have suggestions or improvements, let me
* know.
*/
#include "stdafx.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
static char encoder[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decoder[256];
static int initialized;
static void
base64_init_decoder(void)
{
int i = 0;
if (initialized)
{
return;
}
// -1 is used for error detection
memset(decoder, -1, sizeof decoder);
for (; i < 64; decoder[(int) encoder[i]] = i, ++i);
initialized = 1;
return;
}
static int
base64_encsize(int size)
{
return 4 * ((size + 2) / 3);
}
int
base64_encode(char *dest, int size, unsigned char *src, int slen)
{
int dlen, i, j;
uint32_t a, b, c, triple;
dlen = base64_encsize(slen);
// Sanity checks
if (src == NULL || dest == NULL)
{
return -1;
}
if (dlen + 1 > size)
{
return -1;
}
if (slen == 0)
{
if (size > 0)
{
dest[0] = 0;
return 0;
}
return -1;
}
for (i = 0, j = 0; i < slen;)
{
a = src[i++];
// b and c may be off limit
b = i < slen ? src[i++] : 0;
c = i < slen ? src[i++] : 0;
triple = (a << 16) + (b << 8) + c;
dest[j++] = encoder[(triple >> 18) & 0x3F];
dest[j++] = encoder[(triple >> 12) & 0x3F];
dest[j++] = encoder[(triple >> 6) & 0x3F];
dest[j++] = encoder[triple & 0x3F];
}
// Pad zeroes at the end
switch (slen % 3)
{
case 1:
dest[j - 2] = '=';
case 2:
dest[j - 1] = '=';
}
// Always add \0
dest[j] = 0;
return dlen;
}
char *
base64_enc_malloc(unsigned char *src, int slen)
{
int size;
char *buffer;
size = base64_encsize(slen) + 1;
buffer = (char *) malloc(size);
if (buffer == NULL)
{
return NULL;
}
size = base64_encode(buffer, size, src, slen);
if (size == -1)
{
free(buffer);
return NULL;
}
return buffer;
}
static int
base64_decsize(char *src)
{
int slen, size, i;
if (src == NULL)
{
return 0;
}
slen = strlen(src);
size = slen / 4 * 3;
// Count pad chars
for (i = 0 ; src[slen - i - 1] == '='; ++i);
// Remove at most 2 bytes.
return size - (i >= 2? 2: i);
}
int
base64_decode(unsigned char *dest, int size, char *src)
{
int slen, dlen, padlen, i, j;
uint32_t a, b, c, d, triple;
// Initialize decoder
base64_init_decoder();
// Sanity checks
if (src == NULL || dest == NULL)
{
return -1;
}
slen = strlen(src);
if (slen == 0)
{
if (size > 0)
{
dest[0] = 0;
return 0;
}
return -1;
}
// Remove trailing pad characters.
for (padlen = 0; src[slen - padlen - 1] == '='; ++padlen);
if (padlen > 2)
{
slen -= padlen - 2;
}
if (slen % 4)
{
return -1;
}
dlen = base64_decsize(src);
// Check buffer size
if (dlen + 1 > size)
{
return -1;
}
for (i = 0, j = 0; i < slen;)
{
a = decoder[(int) src[i++]];
b = decoder[(int) src[i++]];
c = decoder[(int) src[i++]];
d = decoder[(int) src[i++]];
// Sextet 3 and 4 may be zero at the end
if (i == slen)
{
if (src[slen - 1] == '=')
{
d = 0;
if (src[slen - 2] == '=')
{
c = 0;
}
}
}
// Non-Base64 char
if (a == -1 || b == -1 || c == -1 || d == -1)
{
return -1;
}
triple = (a << 18) + (b << 12) + (c << 6) + d;
if (j < dlen) dest[j++] = (triple >> 16) & 0xFF;
if (j < dlen) dest[j++] = (triple >> 8) & 0xFF;
if (j < dlen) dest[j++] = triple & 0xFF;
}
// Always add \0
dest[j] = 0;
return dlen;
}
unsigned char *
base64_dec_malloc(char *src, int32_t* dec_size)
{
int size;
unsigned char *buffer;
if (dec_size == NULL)
{
return NULL;
}
size = base64_decsize(src) + 1;
buffer = (unsigned char *) malloc(size);
if (buffer == NULL)
{
return NULL;
}
size = base64_decode(buffer, size, src);
if (size == -1)
{
free(buffer);
return NULL;
}
*dec_size = size;
return buffer;
}
#ifdef DEBUG
int
main(void)
{
struct testcase {
char *dec;
char *enc;
int fail;
int reverse;
};
struct testcase cases[] = {
{"MQ==", "1", 0, 1},
{"MTI=", "12", 0, 1},
{"MTIz", "123", 0, 1},
{"MTIzNA==", "1234", 0, 1},
{"SGVsbG8gV29ybGQ=", "Hello World", 0, 1},
{"aGVsbG8gd29ybGQ=", "hello world", 0, 1},
{"Zm9vYmFy", "foobar", 0, 1},
{"YmFyZm9v", "barfoo", 0, 1},
{"dGVzdA==", "test", 0, 1},
// Edge cases
{"", "", 0, 1},
{"dGVzdA===", "test", 0, 0},
{"dGVzdA====", "test", 0, 0},
{"=", NULL, 1, 0},
{"==", NULL, 1, 0},
{"-", NULL, 1, 0},
{"dGVzd=A==", NULL, 1, 0},
{"dGVzd=A=", NULL, 1, 0},
{"d-GVzdA==", NULL, 1, 0},
{"dGVzdA.=", NULL, 1, 0},
{"GVzdA==", NULL, 1, 0},
{NULL, NULL, 0, 0}
};
char *buffer;
struct testcase *tc;
for (tc = cases; tc->dec; ++tc)
{
// Decode
buffer = (char *) base64_dec_malloc(tc->dec);
if (tc->fail)
{
assert(buffer == NULL);
continue;
}
assert(buffer != NULL);
assert(strcmp(buffer, tc->enc) == 0);
free(buffer);
// Encode
if (tc->reverse)
{
buffer = base64_enc_malloc((unsigned char *) tc->enc, strlen(tc->enc));
assert(buffer != NULL);
assert(strcmp(buffer, tc->dec) == 0);
free(buffer);
}
}
return 0;
}
#endif

View File

@@ -0,0 +1,13 @@
/*
* Written by Manuel Badzong. If you have suggestions or improvements, let me
* know.
*/
#ifndef _BASE64_H_
#define _BASE64_H_
int base64_encode(char *dest, int size, unsigned char *src, int slen);
char *base64_enc_malloc(unsigned char *src, int slen);
int base64_decode(unsigned char *dest, int size, char *src);
unsigned char *base64_dec_malloc(char *src, int32_t* dec_size);
#endif

View File

@@ -0,0 +1,22 @@
#if defined( _WIN32 )
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g_audio", "g_audio.vcxproj", "{1EB632F7-46B4-486C-A9C0-5919F46BB496}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Debug|x64.ActiveCfg = Debug|x64
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Debug|x64.Build.0 = Debug|x64
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Debug|x86.ActiveCfg = Debug|Win32
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Debug|x86.Build.0 = Debug|Win32
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Release|x64.ActiveCfg = Release|x64
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Release|x64.Build.0 = Release|x64
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Release|x86.ActiveCfg = Release|Win32
{1EB632F7-46B4-486C-A9C0-5919F46BB496}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1EB632F7-46B4-486C-A9C0-5919F46BB496}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>g_audio</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>g_audio</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>$(ProjectName)_$(PlatformArchitecture)_DEBUG</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetName>$(ProjectName)_$(PlatformArchitecture)_DEBUG</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<TargetName>$(ProjectName)_$(PlatformArchitecture)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetName>$(ProjectName)_$(PlatformArchitecture)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;G_AUDIO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;G_AUDIO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;G_AUDIO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ImageHasSafeExceptionHandlers>true</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(OutDir)$(TargetFileName)" "$(SolutionDir)..\LabVIEW\G-Audio\lib\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;G_AUDIO_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PostBuildEvent>
<Command>copy /Y "$(OutDir)$(TargetFileName)" "$(SolutionDir)..\LabVIEW\G-Audio\lib\$(TargetFileName)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="base64.h" />
<ClInclude Include="dr_flac.h" />
<ClInclude Include="g_audio.h" />
<ClInclude Include="dr_wav.h" />
<ClInclude Include="id3tag.h" />
<ClInclude Include="miniaudio.h" />
<ClInclude Include="minimp3.h" />
<ClInclude Include="minimp3_ex.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stb_image.h" />
<ClInclude Include="stb_vorbis.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="thread_safety.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="base64.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="g_audio.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thread_safety.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="g_audio.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dr_wav.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="minimp3_ex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="minimp3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thread_safety.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="g_audio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stb_vorbis.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dr_flac.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="miniaudio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="id3tag.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stb_image.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="base64.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thread_safety.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="g_audio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="base64.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="g_audio.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
#!/bin/bash
OUTPUT_PATH=../LabVIEW/G-Audio/lib
mkdir -p $OUTPUT_PATH
g++ -shared -fPIC -o g_audio_64.so *.cpp -lm -lpthread -ldl -O3
mv g_audio_64.so $OUTPUT_PATH

View File

@@ -0,0 +1,5 @@
#!/bin/bash
OUTPUT_PATH=/usr/lib
g++ -shared -fPIC -o g_audio_32.so *.cpp -lm -lpthread -ldl -std=c++11 -mfpu=neon -mfloat-abi=softfp -O3
mv g_audio_32.so $OUTPUT_PATH

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by g_audio.rc
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// g_audio.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@@ -0,0 +1,21 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#if defined( _WIN32 )
#define _CRT_NONSTDC_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#include "targetver.h"
//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#endif
// TODO: reference additional headers your program requires here

View File

@@ -0,0 +1,8 @@
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

View File

@@ -0,0 +1,674 @@
/*
------------------------------------------------------------------------------
Licensing information can be found at the end of the file.
------------------------------------------------------------------------------
thread.h - v0.3 - Cross platform threading functions for C/C++.
Modified to include only mutex functions. Threading functions had compilation
issues when built on Windows not using Visual Studio.
Do this:
#define THREAD_IMPLEMENTATION
before you include this file in *one* C/C++ file to create the implementation.
*/
#ifndef thread_h
#define thread_h
#ifndef THREAD_U64
#define THREAD_U64 unsigned long long
#endif
#define THREAD_STACK_SIZE_DEFAULT ( 0 )
#define THREAD_SIGNAL_WAIT_INFINITE ( -1 )
#define THREAD_QUEUE_WAIT_INFINITE ( -1 )
typedef union thread_mutex_t thread_mutex_t;
void thread_mutex_init( thread_mutex_t* mutex );
void thread_mutex_term( thread_mutex_t* mutex );
void thread_mutex_lock( thread_mutex_t* mutex );
void thread_mutex_unlock( thread_mutex_t* mutex );
#endif /* thread_h */
/**
Example
=======
Here's a basic sample program which starts a second thread which just waits and prints a message.
#define THREAD_IMPLEMENTATION
#include "thread.h"
#include <stdio.h> // for printf
int thread_proc( void* user_data)
{
thread_timer_t timer;
thread_timer_init( &timer );
int count = 0;
thread_atomic_int_t* exit_flag = (thread_atomic_int_t*) user_data;
while( thread_atomic_int_load( exit_flag ) == 0 )
{
printf( "Thread... " );
thread_timer_wait( &timer, 1000000000 ); // sleep for a second
++count;
}
thread_timer_term( &timer );
printf( "Done\n" );
return count;
}
int main( int argc, char** argv )
{
(void) argc, argv;
thread_atomic_int_t exit_flag;
thread_atomic_int_store( &exit_flag, 0 );
thread_ptr_t thread = thread_create( thread_proc, &exit_flag, "Example thread", THREAD_STACK_SIZE_DEFAULT );
thread_timer_t timer;
thread_timer_init( &timer );
for( int i = 0; i < 5; ++i )
{
printf( "Main... " );
thread_timer_wait( &timer, 2000000000 ); // sleep for two seconds
}
thread_timer_term( &timer );
thread_atomic_int_store( &exit_flag, 1 ); // signal thread to exit
int retval = thread_join( thread );
printf( "Count: %d\n", retval );
thread_destroy( thread );
return retval;
}
API Documentation
=================
thread.h is a single-header library, and does not need any .lib files or other binaries, or any build scripts. To use it,
you just include thread.h to get the API declarations. To get the definitions, you must include thread.h from *one*
single C or C++ file, and #define the symbol `THREAD_IMPLEMENTATION` before you do.
Customization
-------------
thread.h allows for specifying the exact type of 64-bit unsigned integer to be used in its API. By default, it is
defined as `unsigned long long`, but as this is not a standard type on all compilers, you can redefine it by #defining
THREAD_U64 before including thread.h. This is useful if you, for example, use the types from `<stdint.h>` in the rest of
your program, and you want thread.h to use compatible types. In this case, you would include thread.h using the
following code:
#define THREAD_U64 uint64_t
#include "thread.h"
Note that when customizing this data type, you need to use the same definition in every place where you include
thread.h, as it affect the declarations as well as the definitions.
thread_current_thread_id
------------------------
thread_id_t thread_current_thread_id( void )
Returns a unique identifier for the calling thread. After the thread terminates, the id might be reused for new threads.
thread_yield
------------
void thread_yield( void )
Makes the calling thread yield execution to another thread. The operating system controls which thread is switched to.
thread_set_high_priority
------------------------
void thread_set_high_priority( void )
When created, threads are set to run at normal priority. In some rare cases, such as a sound buffer update loop, it can
be necessary to have one thread of your application run on a higher priority than the rest. Calling
`thread_set_high_priority` will raise the priority of the calling thread, giving it a chance to be run more often.
Do not increase the priority of a thread unless you absolutely have to, as it can negatively affect performance if used
without care.
thread_exit
-----------
void thread_exit( int return_code )
Exits the calling thread, as if you had done `return return_code;` from the main body of the thread function.
thread_create
-------------
thread_ptr_t thread_create( int (*thread_proc)( void* ), void* user_data, char const* name, int stack_size )
Creates a new thread running the `thread_proc` function, passing the `user_data` through to it. The thread will be
given the debug name given in the `name` parameter, if supported on the platform, and it will have the stack size
specified in the `stack_size` parameter. To get the operating system default stack size, use the defined constant
`THREAD_STACK_SIZE_DEFAULT`. When returning from the thread_proc function, the value you return can be received in
another thread by calling thread_join. `thread_create` returns a pointer to the thread instance, which can be used
as a parameter to the functions `thread_destroy` and `thread_join`.
thread_destroy
--------------
void thread_destroy( thread_ptr_t thread )
Destroys a thread that was created by calling `thread_create`. Make sure the thread has exited before you attempt to
destroy it. This can be accomplished by calling `thread_join`. It is not possible for force termination of a thread by
calling `thread_destroy`.
thread_join
-----------
int thread_join( thread_ptr_t thread )
Waits for the specified thread to exit. Returns the value which the thread returned when exiting.
thread_mutex_init
-----------------
void thread_mutex_init( thread_mutex_t* mutex )
Initializes the specified mutex instance, preparing it for use. A mutex can be used to lock sections of code, such that
it can only be run by one thread at a time.
thread_mutex_term
-----------------
void thread_mutex_term( thread_mutex_t* mutex )
Terminates the specified mutex instance, releasing any system resources held by it.
thread_mutex_lock
-----------------
void thread_mutex_lock( thread_mutex_t* mutex )
Takes an exclusive lock on a mutex. If the lock is already taken by another thread, `thread_mutex_lock` will yield the
calling thread and wait for the lock to become available before returning. The mutex must be initialized by calling
`thread_mutex_init` before it can be locked.
thread_mutex_unlock
-------------------
void thread_mutex_unlock( thread_mutex_t* mutex )
Releases a lock taken by calling `thread_mutex_lock`.
thread_signal_init
------------------
void thread_signal_init( thread_signal_t* signal )
Initializes the specified signal instance, preparing it for use. A signal works like a flag, which can be waited on by
one thread, until it is raised from another thread.
thread_signal_term
------------------
void thread_signal_term( thread_signal_t* signal )
Terminates the specified signal instance, releasing any system resources held by it.
thread_signal_raise
-------------------
void thread_signal_raise( thread_signal_t* signal )
Raise the specified signal. Other threads waiting for the signal will proceed.
thread_signal_wait
------------------
int thread_signal_wait( thread_signal_t* signal, int timeout_ms )
Waits for a signal to be raised, or until `timeout_ms` milliseconds have passed. If the wait timed out, a value of 0 is
returned, otherwise a non-zero value is returned. If the `timeout_ms` parameter is THREAD_SIGNAL_WAIT_INFINITE,
`thread_signal_wait` waits indefinitely.
thread_atomic_int_load
----------------------
int thread_atomic_int_load( thread_atomic_int_t* atomic )
Returns the value of `atomic` as an atomic operation.
thread_atomic_int_store
-----------------------
void thread_atomic_int_store( thread_atomic_int_t* atomic, int desired )
Sets the value of `atomic` as an atomic operation.
thread_atomic_int_inc
---------------------
int thread_atomic_int_inc( thread_atomic_int_t* atomic )
Increments the value of `atomic` by one, as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_int_dec
---------------------
int thread_atomic_int_dec( thread_atomic_int_t* atomic )
Decrements the value of `atomic` by one, as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_int_add
---------------------
int thread_atomic_int_add( thread_atomic_int_t* atomic, int value )
Adds the specified value to `atomic`, as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_int_sub
---------------------
int thread_atomic_int_sub( thread_atomic_int_t* atomic, int value )
Subtracts the specified value to `atomic`, as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_int_swap
----------------------
int thread_atomic_int_swap( thread_atomic_int_t* atomic, int desired )
Sets the value of `atomic` as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_int_compare_and_swap
----------------------------------
int thread_atomic_int_compare_and_swap( thread_atomic_int_t* atomic, int expected, int desired )
Compares the value of `atomic` to the value of `expected`, and if they match, sets the vale of `atomic` to `desired`,
all as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_ptr_load
----------------------
void* thread_atomic_ptr_load( thread_atomic_ptr_t* atomic )
Returns the value of `atomic` as an atomic operation.
thread_atomic_ptr_store
-----------------------
void thread_atomic_ptr_store( thread_atomic_ptr_t* atomic, void* desired )
Sets the value of `atomic` as an atomic operation.
thread_atomic_ptr_swap
----------------------
void* thread_atomic_ptr_swap( thread_atomic_ptr_t* atomic, void* desired )
Sets the value of `atomic` as an atomic operation. Returns the value `atomic` had before the operation.
thread_atomic_ptr_compare_and_swap
----------------------------------
void* thread_atomic_ptr_compare_and_swap( thread_atomic_ptr_t* atomic, void* expected, void* desired )
Compares the value of `atomic` to the value of `expected`, and if they match, sets the vale of `atomic` to `desired`,
all as an atomic operation. Returns the value `atomic` had before the operation.
thread_timer_init
-----------------
void thread_timer_init( thread_timer_t* timer )
Initializes the specified timer instance, preparing it for use. A timer can be used to sleep a thread for a high
precision duration.
thread_timer_term
-----------------
void thread_timer_term( thread_timer_t* timer )
Terminates the specified timer instance, releasing any system resources held by it.
thread_timer_wait
-----------------
void thread_timer_wait( thread_timer_t* timer, THREAD_U64 nanoseconds )
Waits until `nanoseconds` amount of time have passed, before returning.
thread_tls_create
-----------------
thread_tls_t thread_tls_create( void )
Creates a thread local storage (TLS) index. Once created, each thread has its own value for that TLS index, which can
be set or retrieved individually.
thread_tls_destroy
------------------
void thread_tls_destroy( thread_tls_t tls )
Destroys the specified TLS index. No further calls to `thread_tls_set` or `thread_tls_get` are valid after this.
thread_tls_set
--------------
void thread_tls_set( thread_tls_t tls, void* value )
Stores a value in the calling thread's slot for the specified TLS index. Each thread has its own value for each TLS
index.
thread_tls_get
--------------
void* thread_tls_get( thread_tls_t tls )
Retrieves the value from the calling thread's slot for the specified TLS index. Each thread has its own value for each
TLS index.
thread_queue_init
-----------------
void thread_queue_init( thread_queue_t* queue, int size, void** values, int count )
Initializes the specified queue instance, preparing it for use. The queue is a lock-free (but not wait-free)
single-producer/single-consumer queue - it will not acquire any locks as long as there is space for adding or items to
be consume, but will lock and wait when there is not. The `size` parameter specifies the number of elements in the
queue. The `values` parameter is an array of queue slots (`size` elements in length), each being of type `void*`. If
the queue is initially empty, the `count` parameter should be 0, otherwise it indicates the number of entires, from the
start of the `values` array, that the queue is initialized with. The `values` array is not copied, and must remain valid
until `thread_queue_term` is called.
thread_queue_term
-----------------
void thread_queue_term( thread_queue_t* queue )
Terminates the specified queue instance, releasing any system resources held by it.
thread_queue_produce
--------------------
int thread_queue_produce( thread_queue_t* queue, void* value, int timeout_ms )
Adds an element to a single-producer/single-consumer queue. If there is space in the queue to add another element, no
lock will be taken. If the queue is full, calling thread will sleep until an element is consumed from another thread,
before adding the element, or until `timeout_ms` milliseconds have passed. If the wait timed out, a value of 0 is
returned, otherwise a non-zero value is returned. If the `timeout_ms` parameter is THREAD_QUEUE_WAIT_INFINITE,
`thread_queue_produce` waits indefinitely.
thread_queue_consume
--------------------
void* thread_queue_consume( thread_queue_t* queue, int timeout_ms )
Removes an element from a single-producer/single-consumer queue. If the queue contains at least one element, no lock
will be taken. If the queue is empty, the calling thread will sleep until an element is added from another thread, or
until `timeout_ms` milliseconds have passed. If the wait timed out, a value of NULL is returned, otherwise
`thread_queue_consume` returns the value that was removed from the queue. If the `timeout_ms` parameter is
THREAD_QUEUE_WAIT_INFINITE, `thread_queue_consume` waits indefinitely.
thread_queue_count
------------------
int thread_queue_count( thread_queue_t* queue )
Returns the number of elements currently held in a single-producer/single-consumer queue. Be aware that by the time you
get the count, it might have changed by another thread calling consume or produce, so use with care.
**/
/*
----------------------
IMPLEMENTATION
----------------------
*/
#ifndef thread_impl
#define thread_impl
union thread_mutex_t
{
void* align;
char data[ 64 ];
};
#endif /* thread_impl */
#ifdef THREAD_IMPLEMENTATION
#undef THREAD_IMPLEMENTATION
#if defined( _WIN32 )
#pragma comment( lib, "winmm.lib" )
#define _CRT_NONSTDC_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#if !defined( _WIN32_WINNT ) || _WIN32_WINNT < 0x0501
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x501// requires Windows XP minimum
#endif
#define _WINSOCKAPI_
#pragma warning( push )
#pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
#pragma warning( disable: 4255 )
#include <windows.h>
#pragma warning( pop )
// To set thread name
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack( push, 8 )
typedef struct tagTHREADNAME_INFO
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} THREADNAME_INFO;
#pragma pack(pop)
#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __ANDROID__ )
#include <pthread.h>
#include <sys/time.h>
#else
#error Unknown platform.
#endif
#ifndef NDEBUG
#include <assert.h>
#endif
void thread_mutex_init( thread_mutex_t* mutex )
{
#if defined( _WIN32 )
// Compile-time size check
#pragma warning( push )
#pragma warning( disable: 4214 ) // nonstandard extension used: bit field types other than int
struct x { char thread_mutex_type_too_small : ( sizeof( thread_mutex_t ) < sizeof( CRITICAL_SECTION ) ? 0 : 1 ); };
#pragma warning( pop )
InitializeCriticalSectionAndSpinCount( (CRITICAL_SECTION*) mutex, 32 );
#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __ANDROID__ )
// Compile-time size check
struct x { char thread_mutex_type_too_small : ( sizeof( thread_mutex_t ) < sizeof( pthread_mutex_t ) ? 0 : 1 ); };
pthread_mutex_init( (pthread_mutex_t*) mutex, NULL );
#else
#error Unknown platform.
#endif
}
void thread_mutex_term( thread_mutex_t* mutex )
{
#if defined( _WIN32 )
DeleteCriticalSection( (CRITICAL_SECTION*) mutex );
#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __ANDROID__ )
pthread_mutex_destroy( (pthread_mutex_t*) mutex );
#else
#error Unknown platform.
#endif
}
void thread_mutex_lock( thread_mutex_t* mutex )
{
#if defined( _WIN32 )
EnterCriticalSection( (CRITICAL_SECTION*) mutex );
#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __ANDROID__ )
pthread_mutex_lock( (pthread_mutex_t*) mutex );
#else
#error Unknown platform.
#endif
}
void thread_mutex_unlock( thread_mutex_t* mutex )
{
#if defined( _WIN32 )
LeaveCriticalSection( (CRITICAL_SECTION*) mutex );
#elif defined( __linux__ ) || defined( __APPLE__ ) || defined( __ANDROID__ )
pthread_mutex_unlock( (pthread_mutex_t*) mutex );
#else
#error Unknown platform.
#endif
}
#endif /* THREAD_IMPLEMENTATION */
/*
revision history:
0.3 set_high_priority API change. Fixed spurious wakeup bug in signal. Added
timeout param to queue produce/consume. Various cleanup and trivial fixes.
0.2 first publicly released version
*/
/*
------------------------------------------------------------------------------
This software is available under 2 licenses - you may choose the one you like.
------------------------------------------------------------------------------
ALTERNATIVE A - MIT License
Copyright (c) 2015 Mattias Gustavsson
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
------------------------------------------------------------------------------
ALTERNATIVE B - Public Domain (www.unlicense.org)
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
software, either in source code form or as a compiled binary, for any purpose,
commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of this
software dedicate any and all copyright interest in the software to the public
domain. We make this dedication for the benefit of the public at large and to
the detriment of our heirs and successors. We intend this dedication to be an
overt act of relinquishment in perpetuity of all present and future rights to
this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
------------------------------------------------------------------------------
*/

View File

@@ -0,0 +1,168 @@
#include "stdafx.h"
#define THREAD_IMPLEMENTATION
#include "thread_safety.h"
// These variables will be kept in memory while LabVIEW has DLL loaded.
// LabVIEW won't unload DLL until entire VI call chain is removed from memory, or explicitly removed by wiring empty path to CLFN.
ga_refnum refnums[ga_refnum_count];
thread_mutex_t ga_mutexes[ga_mutex_count] = { 0 };
// Create the refnums mutex if it doesn't already exist.
// If it does exist, do nothing.
// Could maybe use the CLFN's reserve callback to call this rather than every lock / unlock
static inline void create_refnums_mutex(ga_refnum_type refnum_type)
{
// Init the mutex if it doesn't exist
if (strlen(refnums[refnum_type].refnums_mutex.data) == 0)
{
thread_mutex_init(&(refnums[refnum_type].refnums_mutex));
}
}
// Lock the refnums mutex. Will attempt to create the mutex first in case it doesn't exist.
static void lock_refnums_mutex(ga_refnum_type refnum_type)
{
create_refnums_mutex(refnum_type);
thread_mutex_lock(&(refnums[refnum_type].refnums_mutex));
return;
}
// Unlock the refnums mutex. Will attempt to create the mutex first in case it doesn't exist.
static void unlock_refnums_mutex(ga_refnum_type refnum_type)
{
create_refnums_mutex(refnum_type);
thread_mutex_unlock(&(refnums[refnum_type].refnums_mutex));
return;
}
// Creates a new refnum and stores it and its data into the allocated refnums, returning the new refnum value.
// If the refnum allocation is exhausted, returns -1.
int32_t create_insert_refnum_data(ga_refnum_type refnum_type, void* data)
{
int32_t new_reference = 0;
lock_refnums_mutex(refnum_type);
//// START CRITICAL SECTION ////
do
{
// update reference id
refnums[refnum_type].refnum_counter++;
// Check for roll over of reference counter.
if (refnums[refnum_type].refnum_counter < 0)
{
refnums[refnum_type].refnum_counter = 0;
}
new_reference = refnums[refnum_type].refnum_counter;
if (!refnums[refnum_type].refnums.count(new_reference))
{
refnums[refnum_type].refnums[new_reference] = data;
break;
}
// Check if maximum reference allocation has been reached.
else if (refnums[refnum_type].refnums.size() >= INT_MAX)
{
new_reference = -1;
break;
}
} while (1);
//// END CRITICAL SECTION ////
unlock_refnums_mutex(refnum_type);
return new_reference;
}
// Updates the data in the refnum allocation for the given refnum.
void update_reference_data(ga_refnum_type refnum_type, int32_t reference, void * data)
{
lock_refnums_mutex(refnum_type);
//// START CRITICAL SECTION ////
if (refnums[refnum_type].refnums.count(reference))
{
refnums[refnum_type].refnums[reference] = data;
}
//// END CRITICAL SECTION ////
unlock_refnums_mutex(refnum_type);
}
// Retrieves the data in the refnum allocation for the given refnum.
void* get_reference_data(ga_refnum_type refnum_type, int32_t reference)
{
void* data = NULL;
lock_refnums_mutex(refnum_type);
//// START CRITICAL SECTION ////
if (refnums[refnum_type].refnums.count(reference))
{
data = refnums[refnum_type].refnums[reference];
}
//// END CRITICAL SECTION ////
unlock_refnums_mutex(refnum_type);
return data;
}
// Removes the refnum from the refnum allocation, returning its data.
// The caller is responsible for freeing the data.
void* remove_reference(ga_refnum_type refnum_type, int32_t reference)
{
void* data = NULL;
lock_refnums_mutex(refnum_type);
//// START CRITICAL SECTION ////
if (refnums[refnum_type].refnums.count(reference))
{
data = refnums[refnum_type].refnums[reference];
refnums[refnum_type].refnums.erase(reference);
}
//// END CRITICAL SECTION ////
unlock_refnums_mutex(refnum_type);
return data;
}
std::vector<int32_t> get_all_references(ga_refnum_type refnum_type)
{
std::vector<int32_t> all_refnums;
lock_refnums_mutex(refnum_type);
//// START CRITICAL SECTION ////
for (std::unordered_map<int32_t, void*>::iterator it = refnums[refnum_type].refnums.begin(); it != refnums[refnum_type].refnums.end(); ++it)
{
all_refnums.push_back(it->first);
}
//// END CRITICAL SECTION ////
unlock_refnums_mutex(refnum_type);
return all_refnums;
}
// Create the context mutex if it doesn't already exist.
// If it does exist, do nothing.
// Could maybe use the CLFN's reserve callback to call this rather than every lock / unlock
inline void create_ga_mutex(ga_mutex_type mutex_type)
{
// Init the mutex if it doesn't exist
if (strlen(ga_mutexes[mutex_type].data) == 0)
{
thread_mutex_init(&ga_mutexes[mutex_type]);
}
}
// Lock the context mutex. Will attempt to create the mutex first in case it doesn't exist.
void lock_ga_mutex(ga_mutex_type mutex_type)
{
create_ga_mutex(mutex_type);
thread_mutex_lock(&ga_mutexes[mutex_type]);
return;
}
// Unlock the context mutex. Will attempt to create the mutex first in case it doesn't exist.
void unlock_ga_mutex(ga_mutex_type mutex_type)
{
create_ga_mutex(mutex_type);
thread_mutex_unlock(&ga_mutexes[mutex_type]);
return;
}

View File

@@ -0,0 +1,53 @@
#ifndef _THREAD_SAFETY_
#define _THREAD_SAFETY_
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unordered_map>
#include <vector>
// Need to #define THREAD_IMPLEMENTATION before including thread.h
// Don't do it in this header, as it will cause linkage issues
// Instead define it in thread_safety.cpp
#include "thread.h"
#include "miniaudio.h"
typedef struct ga_refnum
{
std::unordered_map<int32_t, void*> refnums;
thread_mutex_t refnums_mutex = { 0 };
int32_t refnum_counter = 0;
} ga_refnum;
typedef enum
{
ga_refnum_audio_file = 0,
ga_refnum_audio_device,
ga_refnum_count
} ga_refnum_type;
typedef enum
{
ga_mutex_common = 0,
ga_mutex_context,
ga_mutex_device,
ga_mutex_count
} ga_mutex_type;
static inline void create_refnums_mutex(ga_refnum_type refnum_type);
static void lock_refnums_mutex(ga_refnum_type refnum_type);
static void unlock_refnums_mutex(ga_refnum_type refnum_type);
inline void create_ga_mutex(ga_mutex_type mutex_type);
void lock_ga_mutex(ga_mutex_type mutex_type);
void unlock_ga_mutex(ga_mutex_type mutex_type);
// Create and insert a new unique reference to the global references
int32_t create_insert_refnum_data(ga_refnum_type refnum_type, void* data);
void update_reference_data(ga_refnum_type refnum_type, int32_t reference, void* data);
void* get_reference_data(ga_refnum_type refnum_type, int32_t reference);
void* remove_reference(ga_refnum_type refnum_type, int32_t reference);
std::vector<int32_t> get_all_references(ga_refnum_type refnum_type);
#endif

View File

@@ -0,0 +1,26 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Gcc Patch
/*.gcno

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string></string>
</dict>
</plist>

View File

@@ -0,0 +1,401 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
3CD6706826E0D1FE0040E196 /* xcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6706626E0D1FE0040E196 /* xcode.h */; settings = {ATTRIBUTES = (Public, ); }; };
3CD6707626E0D2860040E196 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6706E26E0D2860040E196 /* thread.h */; };
3CD6707726E0D2860040E196 /* stb_vorbis.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6706F26E0D2860040E196 /* stb_vorbis.h */; };
3CD6707826E0D2860040E196 /* stdafx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CD6707026E0D2860040E196 /* stdafx.cpp */; };
3CD6707926E0D2860040E196 /* stdafx.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707126E0D2860040E196 /* stdafx.h */; };
3CD6707A26E0D2860040E196 /* thread_safety.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CD6707226E0D2860040E196 /* thread_safety.cpp */; };
3CD6707B26E0D2860040E196 /* thread_safety.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707326E0D2860040E196 /* thread_safety.h */; };
3CD6707C26E0D2860040E196 /* targetver.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707426E0D2860040E196 /* targetver.h */; };
3CD6707D26E0D2860040E196 /* resource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707526E0D2860040E196 /* resource.h */; };
3CD6708126E0D2A40040E196 /* miniaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707E26E0D2A40040E196 /* miniaudio.h */; };
3CD6708226E0D2A40040E196 /* minimp3.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6707F26E0D2A40040E196 /* minimp3.h */; };
3CD6708326E0D2A40040E196 /* minimp3_ex.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6708026E0D2A40040E196 /* minimp3_ex.h */; };
3CD6708626E0D2B00040E196 /* g_audio.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6708426E0D2B00040E196 /* g_audio.h */; };
3CD6708726E0D2B00040E196 /* g_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CD6708526E0D2B00040E196 /* g_audio.cpp */; };
3CD6708B26E0D2CB0040E196 /* dllmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3CD6708826E0D2CA0040E196 /* dllmain.cpp */; };
3CD6708C26E0D2CB0040E196 /* dr_wav.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6708926E0D2CB0040E196 /* dr_wav.h */; };
3CD6708D26E0D2CB0040E196 /* dr_flac.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CD6708A26E0D2CB0040E196 /* dr_flac.h */; };
3CD6708F26E0D3C80040E196 /* g_audio in Resources */ = {isa = PBXBuildFile; fileRef = 3CD6708E26E0D3C70040E196 /* g_audio */; };
E513406328709686005700A8 /* id3tag.h in Headers */ = {isa = PBXBuildFile; fileRef = E513405F28709685005700A8 /* id3tag.h */; };
E513406428709686005700A8 /* base64.h in Headers */ = {isa = PBXBuildFile; fileRef = E513406028709686005700A8 /* base64.h */; };
E513406528709686005700A8 /* stb_image.h in Headers */ = {isa = PBXBuildFile; fileRef = E513406128709686005700A8 /* stb_image.h */; };
E513406628709686005700A8 /* base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E513406228709686005700A8 /* base64.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
3CD6706326E0D1FE0040E196 /* g_audio_64.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = g_audio_64.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3CD6706626E0D1FE0040E196 /* xcode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xcode.h; sourceTree = "<group>"; };
3CD6706E26E0D2860040E196 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = thread.h; path = ../thread.h; sourceTree = "<group>"; };
3CD6706F26E0D2860040E196 /* stb_vorbis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_vorbis.h; path = ../stb_vorbis.h; sourceTree = "<group>"; };
3CD6707026E0D2860040E196 /* stdafx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stdafx.cpp; path = ../stdafx.cpp; sourceTree = "<group>"; };
3CD6707126E0D2860040E196 /* stdafx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stdafx.h; path = ../stdafx.h; sourceTree = "<group>"; };
3CD6707226E0D2860040E196 /* thread_safety.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = thread_safety.cpp; path = ../thread_safety.cpp; sourceTree = "<group>"; };
3CD6707326E0D2860040E196 /* thread_safety.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = thread_safety.h; path = ../thread_safety.h; sourceTree = "<group>"; };
3CD6707426E0D2860040E196 /* targetver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = targetver.h; path = ../targetver.h; sourceTree = "<group>"; };
3CD6707526E0D2860040E196 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = resource.h; path = ../resource.h; sourceTree = "<group>"; };
3CD6707E26E0D2A40040E196 /* miniaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = miniaudio.h; path = ../miniaudio.h; sourceTree = "<group>"; };
3CD6707F26E0D2A40040E196 /* minimp3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minimp3.h; path = ../minimp3.h; sourceTree = "<group>"; };
3CD6708026E0D2A40040E196 /* minimp3_ex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minimp3_ex.h; path = ../minimp3_ex.h; sourceTree = "<group>"; };
3CD6708426E0D2B00040E196 /* g_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = g_audio.h; path = ../g_audio.h; sourceTree = "<group>"; };
3CD6708526E0D2B00040E196 /* g_audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = g_audio.cpp; path = ../g_audio.cpp; sourceTree = "<group>"; };
3CD6708826E0D2CA0040E196 /* dllmain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dllmain.cpp; path = ../dllmain.cpp; sourceTree = "<group>"; };
3CD6708926E0D2CB0040E196 /* dr_wav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dr_wav.h; path = ../dr_wav.h; sourceTree = "<group>"; };
3CD6708A26E0D2CB0040E196 /* dr_flac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dr_flac.h; path = ../dr_flac.h; sourceTree = "<group>"; };
3CD6708E26E0D3C70040E196 /* g_audio */ = {isa = PBXFileReference; lastKnownFileType = folder; path = g_audio; sourceTree = "<group>"; };
E513405F28709685005700A8 /* id3tag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = id3tag.h; path = ../id3tag.h; sourceTree = "<group>"; };
E513406028709686005700A8 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base64.h; path = ../base64.h; sourceTree = "<group>"; };
E513406128709686005700A8 /* stb_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stb_image.h; path = ../stb_image.h; sourceTree = "<group>"; };
E513406228709686005700A8 /* base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = base64.cpp; path = ../base64.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3CD6706026E0D1FE0040E196 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3CD6705926E0D1FE0040E196 = {
isa = PBXGroup;
children = (
E513406228709686005700A8 /* base64.cpp */,
E513406028709686005700A8 /* base64.h */,
E513405F28709685005700A8 /* id3tag.h */,
E513406128709686005700A8 /* stb_image.h */,
3CD6708E26E0D3C70040E196 /* g_audio */,
3CD6708826E0D2CA0040E196 /* dllmain.cpp */,
3CD6708A26E0D2CB0040E196 /* dr_flac.h */,
3CD6708926E0D2CB0040E196 /* dr_wav.h */,
3CD6708526E0D2B00040E196 /* g_audio.cpp */,
3CD6708426E0D2B00040E196 /* g_audio.h */,
3CD6707E26E0D2A40040E196 /* miniaudio.h */,
3CD6708026E0D2A40040E196 /* minimp3_ex.h */,
3CD6707F26E0D2A40040E196 /* minimp3.h */,
3CD6707526E0D2860040E196 /* resource.h */,
3CD6706F26E0D2860040E196 /* stb_vorbis.h */,
3CD6707026E0D2860040E196 /* stdafx.cpp */,
3CD6707126E0D2860040E196 /* stdafx.h */,
3CD6707426E0D2860040E196 /* targetver.h */,
3CD6707226E0D2860040E196 /* thread_safety.cpp */,
3CD6707326E0D2860040E196 /* thread_safety.h */,
3CD6706E26E0D2860040E196 /* thread.h */,
3CD6706626E0D1FE0040E196 /* xcode.h */,
3CD6706426E0D1FE0040E196 /* Products */,
);
sourceTree = "<group>";
};
3CD6706426E0D1FE0040E196 /* Products */ = {
isa = PBXGroup;
children = (
3CD6706326E0D1FE0040E196 /* g_audio_64.framework */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
3CD6705E26E0D1FE0040E196 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3CD6708D26E0D2CB0040E196 /* dr_flac.h in Headers */,
3CD6708126E0D2A40040E196 /* miniaudio.h in Headers */,
3CD6707926E0D2860040E196 /* stdafx.h in Headers */,
3CD6708226E0D2A40040E196 /* minimp3.h in Headers */,
3CD6707626E0D2860040E196 /* thread.h in Headers */,
E513406428709686005700A8 /* base64.h in Headers */,
3CD6707D26E0D2860040E196 /* resource.h in Headers */,
3CD6708326E0D2A40040E196 /* minimp3_ex.h in Headers */,
3CD6707726E0D2860040E196 /* stb_vorbis.h in Headers */,
3CD6707B26E0D2860040E196 /* thread_safety.h in Headers */,
3CD6708626E0D2B00040E196 /* g_audio.h in Headers */,
E513406328709686005700A8 /* id3tag.h in Headers */,
E513406528709686005700A8 /* stb_image.h in Headers */,
3CD6708C26E0D2CB0040E196 /* dr_wav.h in Headers */,
3CD6706826E0D1FE0040E196 /* xcode.h in Headers */,
3CD6707C26E0D2860040E196 /* targetver.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3CD6706226E0D1FE0040E196 /* g_audio_64 */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3CD6706B26E0D1FE0040E196 /* Build configuration list for PBXNativeTarget "g_audio_64" */;
buildPhases = (
3CD6705E26E0D1FE0040E196 /* Headers */,
3CD6705F26E0D1FE0040E196 /* Sources */,
3CD6706026E0D1FE0040E196 /* Frameworks */,
3CD6706126E0D1FE0040E196 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = g_audio_64;
productName = g_audio;
productReference = 3CD6706326E0D1FE0040E196 /* g_audio_64.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
3CD6705A26E0D1FE0040E196 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = Dataflow_G;
TargetAttributes = {
3CD6706226E0D1FE0040E196 = {
CreatedOnToolsVersion = 11.5;
};
};
};
buildConfigurationList = 3CD6705D26E0D1FE0040E196 /* Build configuration list for PBXProject "g_audio_64" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 3CD6705926E0D1FE0040E196;
productRefGroup = 3CD6706426E0D1FE0040E196 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
3CD6706226E0D1FE0040E196 /* g_audio_64 */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
3CD6706126E0D1FE0040E196 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3CD6708F26E0D3C80040E196 /* g_audio in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3CD6705F26E0D1FE0040E196 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3CD6707826E0D2860040E196 /* stdafx.cpp in Sources */,
3CD6708B26E0D2CB0040E196 /* dllmain.cpp in Sources */,
3CD6707A26E0D2860040E196 /* thread_safety.cpp in Sources */,
E513406628709686005700A8 /* base64.cpp in Sources */,
3CD6708726E0D2B00040E196 /* g_audio.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
3CD6706926E0D1FE0040E196 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
3CD6706A26E0D1FE0040E196 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
3CD6706C26E0D1FE0040E196 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = g_audio/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.7;
MARKETING_VERSION = 0.4.0;
PRODUCT_BUNDLE_IDENTIFIER = "dataflowg.g-audio";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Debug;
};
3CD6706D26E0D1FE0040E196 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = g_audio/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.7;
MARKETING_VERSION = 0.4.0;
PRODUCT_BUNDLE_IDENTIFIER = "dataflowg.g-audio";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3CD6705D26E0D1FE0040E196 /* Build configuration list for PBXProject "g_audio_64" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3CD6706926E0D1FE0040E196 /* Debug */,
3CD6706A26E0D1FE0040E196 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
3CD6706B26E0D1FE0040E196 /* Build configuration list for PBXNativeTarget "g_audio_64" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3CD6706C26E0D1FE0040E196 /* Debug */,
3CD6706D26E0D1FE0040E196 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 3CD6705A26E0D1FE0040E196 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/dataflowg/github/g-audio/src/C++/xcode/g_audio_64.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<PostActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Script"
scriptText = "# Type a script or drag a script file from your workspace to insert its path.&#10;cd $BUILT_PRODUCTS_DIR&#10;rm -f g_audio_64.framework.zip&#10;zip --symlinks -r g_audio_64.framework.zip g_audio_64.framework&#10;cp -R g_audio_64.framework $PROJECT_DIR/../../LabVIEW/G-Audio/lib/&#10;mv g_audio_64.framework.zip $PROJECT_DIR/../../LabVIEW/G-Audio/lib/&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3CD6706226E0D1FE0040E196"
BuildableName = "g_audio_64.framework"
BlueprintName = "g_audio_64"
ReferencedContainer = "container:g_audio_64.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PostActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3CD6706226E0D1FE0040E196"
BuildableName = "g_audio_64.framework"
BlueprintName = "g_audio_64"
ReferencedContainer = "container:g_audio_64.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3CD6706226E0D1FE0040E196"
BuildableName = "g_audio_64.framework"
BlueprintName = "g_audio_64"
ReferencedContainer = "container:g_audio_64.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,19 @@
//
// g_audio.h
// g_audio
//
// Created by Dataflow_G on 9/2/21.
// Copyright © 2021 Dataflow_G. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for g_audio.
FOUNDATION_EXPORT double g_audioVersionNumber;
//! Project version string for g_audio.
FOUNDATION_EXPORT const unsigned char g_audioVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <g_audio/PublicHeader.h>

View File

@@ -0,0 +1,258 @@
<?xml version='1.0' encoding='UTF-8'?>
<Project Type="Project" LVVersion="20008000">
<Property Name="CCSymbols" Type="Str">DEBUG_LIB,FALSE;</Property>
<Property Name="NI.LV.All.SourceOnly" Type="Bool">true</Property>
<Property Name="NI.Project.Description" Type="Str"></Property>
<Property Name="utf.calculate.project.code.coverage" Type="Bool">true</Property>
<Property Name="utf.create.arraybrackets" Type="Str">[]</Property>
<Property Name="utf.create.arraythreshold" Type="UInt">100</Property>
<Property Name="utf.create.captureinputvalues" Type="Bool">true</Property>
<Property Name="utf.create.captureoutputvalues" Type="Bool">true</Property>
<Property Name="utf.create.codecoverage.flag" Type="Bool">false</Property>
<Property Name="utf.create.codecoverage.value" Type="UInt">100</Property>
<Property Name="utf.create.editor.flag" Type="Bool">false</Property>
<Property Name="utf.create.editor.path" Type="Path"></Property>
<Property Name="utf.create.nameseparator" Type="Str">/</Property>
<Property Name="utf.create.precision" Type="UInt">6</Property>
<Property Name="utf.create.repetitions" Type="UInt">1</Property>
<Property Name="utf.create.testpath.flag" Type="Bool">false</Property>
<Property Name="utf.create.testpath.path" Type="Path"></Property>
<Property Name="utf.create.timeout.flag" Type="Bool">false</Property>
<Property Name="utf.create.timeout.value" Type="UInt">0</Property>
<Property Name="utf.create.type" Type="UInt">0</Property>
<Property Name="utf.enable.RT.VI.server" Type="Bool">false</Property>
<Property Name="utf.passwords" Type="Bin">'1#!!!!!!!)!%%!Q`````Q:4&gt;(*J&lt;G=!!":!1!!"`````Q!!#6"B=X.X&lt;X*E=Q!"!!%!!!!"!!!!#F652E&amp;-4&amp;.516)!!!!!</Property>
<Property Name="utf.report.atml.create" Type="Bool">false</Property>
<Property Name="utf.report.atml.path" Type="Path">ATML report.xml</Property>
<Property Name="utf.report.atml.view" Type="Bool">false</Property>
<Property Name="utf.report.details.errors" Type="Bool">false</Property>
<Property Name="utf.report.details.failed" Type="Bool">false</Property>
<Property Name="utf.report.details.passed" Type="Bool">false</Property>
<Property Name="utf.report.errors" Type="Bool">true</Property>
<Property Name="utf.report.failed" Type="Bool">true</Property>
<Property Name="utf.report.html.create" Type="Bool">false</Property>
<Property Name="utf.report.html.path" Type="Path">HTML report.html</Property>
<Property Name="utf.report.html.view" Type="Bool">false</Property>
<Property Name="utf.report.passed" Type="Bool">true</Property>
<Property Name="utf.report.skipped" Type="Bool">true</Property>
<Property Name="utf.report.sortby" Type="UInt">1</Property>
<Property Name="utf.report.stylesheet.flag" Type="Bool">false</Property>
<Property Name="utf.report.stylesheet.path" Type="Path"></Property>
<Property Name="utf.report.summary" Type="Bool">true</Property>
<Property Name="utf.report.txt.create" Type="Bool">false</Property>
<Property Name="utf.report.txt.path" Type="Path">ASCII report.txt</Property>
<Property Name="utf.report.txt.view" Type="Bool">false</Property>
<Property Name="utf.run.changed.days" Type="UInt">1</Property>
<Property Name="utf.run.changed.outdated" Type="Bool">false</Property>
<Property Name="utf.run.changed.timestamp" Type="Bin">'1#!!!!!!!%!%%"5!!9*2'&amp;U:3^U;7VF!!%!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</Property>
<Property Name="utf.run.days.flag" Type="Bool">false</Property>
<Property Name="utf.run.includevicallers" Type="Bool">false</Property>
<Property Name="utf.run.logfile.flag" Type="Bool">false</Property>
<Property Name="utf.run.logfile.overwrite" Type="Bool">false</Property>
<Property Name="utf.run.logfile.path" Type="Path">test execution log.txt</Property>
<Property Name="utf.run.modified.last.run.flag" Type="Bool">true</Property>
<Property Name="utf.run.priority.flag" Type="Bool">false</Property>
<Property Name="utf.run.priority.value" Type="UInt">5</Property>
<Property Name="utf.run.statusfile.flag" Type="Bool">false</Property>
<Property Name="utf.run.statusfile.path" Type="Path">test status log.txt</Property>
<Property Name="utf.run.timestamp.flag" Type="Bool">false</Property>
<Item Name="My Computer" Type="My Computer">
<Property Name="server.app.propertiesEnabled" Type="Bool">true</Property>
<Property Name="server.control.propertiesEnabled" Type="Bool">true</Property>
<Property Name="server.tcp.enabled" Type="Bool">false</Property>
<Property Name="server.tcp.port" Type="Int">0</Property>
<Property Name="server.tcp.serviceName" Type="Str">My Computer/VI Server</Property>
<Property Name="server.tcp.serviceName.default" Type="Str">My Computer/VI Server</Property>
<Property Name="server.vi.callsEnabled" Type="Bool">true</Property>
<Property Name="server.vi.propertiesEnabled" Type="Bool">true</Property>
<Property Name="specify.custom.address" Type="Bool">false</Property>
<Item Name="Examples" Type="Folder">
<Item Name="LINX" Type="Folder">
<Item Name="Audio Playback Example (LINX).vi" Type="VI" URL="../G-Audio/Examples/LINX/Audio Playback Example (LINX).vi"/>
<Item Name="Sample Pad Example (LINX).vi" Type="VI" URL="../G-Audio/Examples/LINX/Sample Pad Example (LINX).vi"/>
</Item>
<Item Name="SubVIs" Type="Folder">
<Item Name="Generate Signal Components.vim" Type="VI" URL="../G-Audio/Examples/SubVIs/Generate Signal Components.vim"/>
<Item Name="Music Visualizer (Queue Only).vi" Type="VI" URL="../G-Audio/Examples/SubVIs/Music Visualizer (Queue Only).vi"/>
</Item>
<Item Name="Audio Capture Example.vi" Type="VI" URL="../G-Audio/Examples/Audio Capture Example.vi"/>
<Item Name="Audio File Tags Example.vi" Type="VI" URL="../G-Audio/Examples/Audio File Tags Example.vi"/>
<Item Name="Audio Loopback Example.vi" Type="VI" URL="../G-Audio/Examples/Audio Loopback Example.vi"/>
<Item Name="Audio Playback Example.vi" Type="VI" URL="../G-Audio/Examples/Audio Playback Example.vi"/>
<Item Name="IEEE Float Compare Example.vi" Type="VI" URL="../G-Audio/Examples/IEEE Float Compare Example.vi"/>
<Item Name="Media Player Example.vi" Type="VI" URL="../G-Audio/Examples/Media Player Example.vi"/>
<Item Name="Minimize Memory Example.vi" Type="VI" URL="../G-Audio/Examples/Minimize Memory Example.vi"/>
<Item Name="Mixer Example.vi" Type="VI" URL="../G-Audio/Examples/Mixer Example.vi"/>
<Item Name="Music Visualizer Example.vi" Type="VI" URL="../G-Audio/Examples/Music Visualizer Example.vi"/>
<Item Name="Playback Latency Compare Example.vi" Type="VI" URL="../G-Audio/Examples/Playback Latency Compare Example.vi"/>
<Item Name="Query Audio Devices Example.vi" Type="VI" URL="../G-Audio/Examples/Query Audio Devices Example.vi"/>
<Item Name="Sample Pad Example (Arduino Controller).vi" Type="VI" URL="../G-Audio/Examples/Sample Pad Example (Arduino Controller).vi"/>
<Item Name="Sample Pad Example.vi" Type="VI" URL="../G-Audio/Examples/Sample Pad Example.vi"/>
<Item Name="Write Audio File Example.vi" Type="VI" URL="../G-Audio/Examples/Write Audio File Example.vi"/>
</Item>
<Item Name="Unit Tests" Type="Folder">
<Item Name="Test Configure Audio Device Duplicate.vi" Type="VI" URL="../Unit Tests/Test Configure Audio Device Duplicate.vi"/>
<Item Name="Test Default Audio Device Capture.vi" Type="VI" URL="../Unit Tests/Test Default Audio Device Capture.vi"/>
<Item Name="Test Default Audio Device Playback.vi" Type="VI" URL="../Unit Tests/Test Default Audio Device Playback.vi"/>
<Item Name="Test File Info FLAC.vi" Type="VI" URL="../Unit Tests/Test File Info FLAC.vi"/>
<Item Name="Test File Info MP3.vi" Type="VI" URL="../Unit Tests/Test File Info MP3.vi"/>
<Item Name="Test File Info Vorbis.vi" Type="VI" URL="../Unit Tests/Test File Info Vorbis.vi"/>
<Item Name="Test File Info WAV.vi" Type="VI" URL="../Unit Tests/Test File Info WAV.vi"/>
<Item Name="Test Get Audio Device Configuration.vi" Type="VI" URL="../Unit Tests/Test Get Audio Device Configuration.vi"/>
<Item Name="Test Load FLAC.vi" Type="VI" URL="../Unit Tests/Test Load FLAC.vi"/>
<Item Name="Test Load MP3.vi" Type="VI" URL="../Unit Tests/Test Load MP3.vi"/>
<Item Name="Test Load Vorbis.vi" Type="VI" URL="../Unit Tests/Test Load Vorbis.vi"/>
<Item Name="Test Load WAV.vi" Type="VI" URL="../Unit Tests/Test Load WAV.vi"/>
<Item Name="Test Minimal Audio Device Capture.vi" Type="VI" URL="../Unit Tests/Test Minimal Audio Device Capture.vi"/>
<Item Name="Test Minimal Audio Device Playback.vi" Type="VI" URL="../Unit Tests/Test Minimal Audio Device Playback.vi"/>
<Item Name="Test Open Read Close FLAC.vi" Type="VI" URL="../Unit Tests/Test Open Read Close FLAC.vi"/>
<Item Name="Test Open Read Close MP3.vi" Type="VI" URL="../Unit Tests/Test Open Read Close MP3.vi"/>
<Item Name="Test Open Read Close Vorbis.vi" Type="VI" URL="../Unit Tests/Test Open Read Close Vorbis.vi"/>
<Item Name="Test Open Read Close WAV.vi" Type="VI" URL="../Unit Tests/Test Open Read Close WAV.vi"/>
<Item Name="Test Open Write Close WAV.vi" Type="VI" URL="../Unit Tests/Test Open Write Close WAV.vi"/>
<Item Name="Test Query Audio Backends.vi" Type="VI" URL="../Unit Tests/Test Query Audio Backends.vi"/>
<Item Name="Test Seek Position FLAC.vi" Type="VI" URL="../Unit Tests/Test Seek Position FLAC.vi"/>
<Item Name="Test Seek Position MP3.vi" Type="VI" URL="../Unit Tests/Test Seek Position MP3.vi"/>
<Item Name="Test Seek Position Vorbis.vi" Type="VI" URL="../Unit Tests/Test Seek Position Vorbis.vi"/>
<Item Name="Test Seek Position WAV.vi" Type="VI" URL="../Unit Tests/Test Seek Position WAV.vi"/>
<Item Name="Test Tag Read FLAC.vi" Type="VI" URL="../Unit Tests/Test Tag Read FLAC.vi"/>
<Item Name="Test Tag Read ID3v1.vi" Type="VI" URL="../Unit Tests/Test Tag Read ID3v1.vi"/>
<Item Name="Test Tag Read ID3v2.vi" Type="VI" URL="../Unit Tests/Test Tag Read ID3v2.vi"/>
<Item Name="Test Tag Read Pictures FLAC.vi" Type="VI" URL="../Unit Tests/Test Tag Read Pictures FLAC.vi"/>
<Item Name="Test Tag Read Pictures MP3.vi" Type="VI" URL="../Unit Tests/Test Tag Read Pictures MP3.vi"/>
<Item Name="Test Tag Read Pictures Vorbis.vi" Type="VI" URL="../Unit Tests/Test Tag Read Pictures Vorbis.vi"/>
<Item Name="Test Tag Read Vorbis.vi" Type="VI" URL="../Unit Tests/Test Tag Read Vorbis.vi"/>
<Item Name="Test Tag Read WAV.vi" Type="VI" URL="../Unit Tests/Test Tag Read WAV.vi"/>
<Item Name="Test Unicode Path UTF8.vi" Type="VI" URL="../Unit Tests/Test Unicode Path UTF8.vi"/>
<Item Name="Test Unicode Tag FLAC.vi" Type="VI" URL="../Unit Tests/Test Unicode Tag FLAC.vi"/>
<Item Name="Test Unicode Tag ID3v2.vi" Type="VI" URL="../Unit Tests/Test Unicode Tag ID3v2.vi"/>
<Item Name="Test Unicode Tag Vorbis.vi" Type="VI" URL="../Unit Tests/Test Unicode Tag Vorbis.vi"/>
<Item Name="Waveform Array In Range Comparison.vim" Type="VI" URL="../Unit Tests/Waveform Array In Range Comparison.vim"/>
</Item>
<Item Name="G-Audio.lvlib" Type="Library" URL="../G-Audio/G-Audio.lvlib"/>
<Item Name="Dependencies" Type="Dependencies">
<Item Name="vi.lib" Type="Folder">
<Item Name="_2DArrToArrWfms.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/_2DArrToArrWfms.vi"/>
<Item Name="_ArrWfmsTo1DInterleave.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/_ArrWfmsTo1DInterleave.vi"/>
<Item Name="_ArrWfmsTo2DArr.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/_ArrWfmsTo2DArr.vi"/>
<Item Name="_ArrWfmsToData.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/_ArrWfmsToData.vi"/>
<Item Name="_Get Sound Error From Return Value.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/_Get Sound Error From Return Value.vi"/>
<Item Name="Application Directory.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/file.llb/Application Directory.vi"/>
<Item Name="Assert Floating-Point Numeric Type.vim" Type="VI" URL="/&lt;vilib&gt;/Utility/TypeAssert/Assert Floating-Point Numeric Type.vim"/>
<Item Name="Assert Signed Integer Type.vim" Type="VI" URL="/&lt;vilib&gt;/Utility/TypeAssert/Assert Signed Integer Type.vim"/>
<Item Name="Assert Unsigned Integer Type.vim" Type="VI" URL="/&lt;vilib&gt;/Utility/TypeAssert/Assert Unsigned Integer Type.vim"/>
<Item Name="Bit-array To Byte-array.vi" Type="VI" URL="/&lt;vilib&gt;/picture/pictutil.llb/Bit-array To Byte-array.vi"/>
<Item Name="BuildHelpPath.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/BuildHelpPath.vi"/>
<Item Name="Calc Long Word Padded Width.vi" Type="VI" URL="/&lt;vilib&gt;/picture/bmp.llb/Calc Long Word Padded Width.vi"/>
<Item Name="Check Path.vi" Type="VI" URL="/&lt;vilib&gt;/picture/jpeg.llb/Check Path.vi"/>
<Item Name="Check Special Tags.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Check Special Tags.vi"/>
<Item Name="Clear Errors.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Clear Errors.vi"/>
<Item Name="Color to RGB.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/colorconv.llb/Color to RGB.vi"/>
<Item Name="Convert property node font to graphics font.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Convert property node font to graphics font.vi"/>
<Item Name="Create Mask By Alpha.vi" Type="VI" URL="/&lt;vilib&gt;/picture/picture.llb/Create Mask By Alpha.vi"/>
<Item Name="Details Display Dialog.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Details Display Dialog.vi"/>
<Item Name="DialogType.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/DialogType.ctl"/>
<Item Name="DialogTypeEnum.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/DialogTypeEnum.ctl"/>
<Item Name="Directory of Top Level VI.vi" Type="VI" URL="/&lt;vilib&gt;/picture/jpeg.llb/Directory of Top Level VI.vi"/>
<Item Name="Draw Flattened Pixmap.vi" Type="VI" URL="/&lt;vilib&gt;/picture/picture.llb/Draw Flattened Pixmap.vi"/>
<Item Name="Error Cluster From Error Code.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Error Cluster From Error Code.vi"/>
<Item Name="Error Code Database.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Error Code Database.vi"/>
<Item Name="ErrWarn.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/ErrWarn.ctl"/>
<Item Name="eventvkey.ctl" Type="VI" URL="/&lt;vilib&gt;/event_ctls.llb/eventvkey.ctl"/>
<Item Name="ex_CorrectErrorChain.vi" Type="VI" URL="/&lt;vilib&gt;/express/express shared/ex_CorrectErrorChain.vi"/>
<Item Name="Find Tag.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Find Tag.vi"/>
<Item Name="FixBadRect.vi" Type="VI" URL="/&lt;vilib&gt;/picture/pictutil.llb/FixBadRect.vi"/>
<Item Name="Flip and Pad for Picture Control.vi" Type="VI" URL="/&lt;vilib&gt;/picture/bmp.llb/Flip and Pad for Picture Control.vi"/>
<Item Name="Format Message String.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Format Message String.vi"/>
<Item Name="General Error Handler Core CORE.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/General Error Handler Core CORE.vi"/>
<Item Name="General Error Handler.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/General Error Handler.vi"/>
<Item Name="Get Memory Status.vi" Type="VI" URL="/&lt;vilib&gt;/MemoryControl/Get Memory Status.vi"/>
<Item Name="Get String Text Bounds.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Get String Text Bounds.vi"/>
<Item Name="Get System Directory.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/sysdir.llb/Get System Directory.vi"/>
<Item Name="Get Text Rect.vi" Type="VI" URL="/&lt;vilib&gt;/picture/picture.llb/Get Text Rect.vi"/>
<Item Name="GetHelpDir.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/GetHelpDir.vi"/>
<Item Name="GetRTHostConnectedProp.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/GetRTHostConnectedProp.vi"/>
<Item Name="imagedata.ctl" Type="VI" URL="/&lt;vilib&gt;/picture/picture.llb/imagedata.ctl"/>
<Item Name="Is Path and Not Empty.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/file.llb/Is Path and Not Empty.vi"/>
<Item Name="liblinxdevice.dll" Type="Document" URL="/&lt;vilib&gt;/MakerHub/LINX/Resources/liblinxdevice.dll"/>
<Item Name="LMH-LINX.lvlib" Type="Library" URL="/&lt;vilib&gt;/MakerHub/LINX/LMH-LINX.lvlib"/>
<Item Name="Longest Line Length in Pixels.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Longest Line Length in Pixels.vi"/>
<Item Name="LVBoundsTypeDef.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/miscctls.llb/LVBoundsTypeDef.ctl"/>
<Item Name="LVNumericRepresentation.ctl" Type="VI" URL="/&lt;vilib&gt;/numeric/LVNumericRepresentation.ctl"/>
<Item Name="LVRectTypeDef.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/miscctls.llb/LVRectTypeDef.ctl"/>
<Item Name="NI_AALBase.lvlib" Type="Library" URL="/&lt;vilib&gt;/Analysis/NI_AALBase.lvlib"/>
<Item Name="NI_AALPro.lvlib" Type="Library" URL="/&lt;vilib&gt;/Analysis/NI_AALPro.lvlib"/>
<Item Name="NI_Data Type.lvlib" Type="Library" URL="/&lt;vilib&gt;/Utility/Data Type/NI_Data Type.lvlib"/>
<Item Name="NI_FileType.lvlib" Type="Library" URL="/&lt;vilib&gt;/Utility/lvfile.llb/NI_FileType.lvlib"/>
<Item Name="NI_MABase.lvlib" Type="Library" URL="/&lt;vilib&gt;/measure/NI_MABase.lvlib"/>
<Item Name="NI_PtbyPt.lvlib" Type="Library" URL="/&lt;vilib&gt;/ptbypt/NI_PtbyPt.lvlib"/>
<Item Name="Not Found Dialog.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Not Found Dialog.vi"/>
<Item Name="Path To Command Line String.vi" Type="VI" URL="/&lt;vilib&gt;/AdvancedString/Path To Command Line String.vi"/>
<Item Name="PathToUNIXPathString.vi" Type="VI" URL="/&lt;vilib&gt;/Platform/CFURL.llb/PathToUNIXPathString.vi"/>
<Item Name="Range Limits for Type.vim" Type="VI" URL="/&lt;vilib&gt;/numeric/Range Limits for Type.vim"/>
<Item Name="Read BMP File Data.vi" Type="VI" URL="/&lt;vilib&gt;/picture/bmp.llb/Read BMP File Data.vi"/>
<Item Name="Read BMP File.vi" Type="VI" URL="/&lt;vilib&gt;/picture/bmp.llb/Read BMP File.vi"/>
<Item Name="Read BMP Header Info.vi" Type="VI" URL="/&lt;vilib&gt;/picture/bmp.llb/Read BMP Header Info.vi"/>
<Item Name="Read JPEG File.vi" Type="VI" URL="/&lt;vilib&gt;/picture/jpeg.llb/Read JPEG File.vi"/>
<Item Name="Read PNG File.vi" Type="VI" URL="/&lt;vilib&gt;/picture/png.llb/Read PNG File.vi"/>
<Item Name="RGB to Color.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/colorconv.llb/RGB to Color.vi"/>
<Item Name="Sampling Mode.ctl" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sampling Mode.ctl"/>
<Item Name="Search and Replace Pattern.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Search and Replace Pattern.vi"/>
<Item Name="Set Bold Text.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Set Bold Text.vi"/>
<Item Name="Set String Value.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Set String Value.vi"/>
<Item Name="Simple Error Handler.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Simple Error Handler.vi"/>
<Item Name="Sound Data Format.ctl" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Data Format.ctl"/>
<Item Name="Sound File Close.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Close.vi"/>
<Item Name="Sound File Info (path).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Info (path).vi"/>
<Item Name="Sound File Info (refnum).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Info (refnum).vi"/>
<Item Name="Sound File Info.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Info.vi"/>
<Item Name="Sound File Open.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Open.vi"/>
<Item Name="Sound File Position.ctl" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Position.ctl"/>
<Item Name="Sound File Read (DBL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read (DBL).vi"/>
<Item Name="Sound File Read (I16).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read (I16).vi"/>
<Item Name="Sound File Read (I32).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read (I32).vi"/>
<Item Name="Sound File Read (SGL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read (SGL).vi"/>
<Item Name="Sound File Read (U8).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read (U8).vi"/>
<Item Name="Sound File Read Open.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read Open.vi"/>
<Item Name="Sound File Read.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Read.vi"/>
<Item Name="Sound File Refnum.ctl" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Refnum.ctl"/>
<Item Name="Sound File Write (DBL Single).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (DBL Single).vi"/>
<Item Name="Sound File Write (DBL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (DBL).vi"/>
<Item Name="Sound File Write (I16).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (I16).vi"/>
<Item Name="Sound File Write (I32).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (I32).vi"/>
<Item Name="Sound File Write (SGL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (SGL).vi"/>
<Item Name="Sound File Write (U8).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write (U8).vi"/>
<Item Name="Sound File Write Open.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write Open.vi"/>
<Item Name="Sound File Write.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound File Write.vi"/>
<Item Name="Sound Output Clear.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Clear.vi"/>
<Item Name="Sound Output Configure.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Configure.vi"/>
<Item Name="Sound Output Start.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Start.vi"/>
<Item Name="Sound Output Stop.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Stop.vi"/>
<Item Name="Sound Output Task ID.ctl" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Task ID.ctl"/>
<Item Name="Sound Output Wait.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Wait.vi"/>
<Item Name="Sound Output Write (DBL Single).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (DBL Single).vi"/>
<Item Name="Sound Output Write (DBL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (DBL).vi"/>
<Item Name="Sound Output Write (I16).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (I16).vi"/>
<Item Name="Sound Output Write (I32).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (I32).vi"/>
<Item Name="Sound Output Write (SGL).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (SGL).vi"/>
<Item Name="Sound Output Write (U8).vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write (U8).vi"/>
<Item Name="Sound Output Write.vi" Type="VI" URL="/&lt;vilib&gt;/sound2/lvsound2.llb/Sound Output Write.vi"/>
<Item Name="subFile Dialog.vi" Type="VI" URL="/&lt;vilib&gt;/express/express input/FileDialogBlock.llb/subFile Dialog.vi"/>
<Item Name="Synchronize Data Flow.vim" Type="VI" URL="/&lt;vilib&gt;/Utility/Synchronize Data Flow.vim"/>
<Item Name="System Directory Type.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/sysdir.llb/System Directory Type.ctl"/>
<Item Name="TagReturnType.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/TagReturnType.ctl"/>
<Item Name="Three Button Dialog CORE.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Three Button Dialog CORE.vi"/>
<Item Name="Three Button Dialog.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Three Button Dialog.vi"/>
<Item Name="Trim Whitespace.vi" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/Trim Whitespace.vi"/>
<Item Name="VISA Configure Serial Port" Type="VI" URL="/&lt;vilib&gt;/Instr/_visa.llb/VISA Configure Serial Port"/>
<Item Name="VISA Configure Serial Port (Instr).vi" Type="VI" URL="/&lt;vilib&gt;/Instr/_visa.llb/VISA Configure Serial Port (Instr).vi"/>
<Item Name="VISA Configure Serial Port (Serial Instr).vi" Type="VI" URL="/&lt;vilib&gt;/Instr/_visa.llb/VISA Configure Serial Port (Serial Instr).vi"/>
<Item Name="whitespace.ctl" Type="VI" URL="/&lt;vilib&gt;/Utility/error.llb/whitespace.ctl"/>
</Item>
<Item Name="g_audio_32.dll" Type="Document" URL="../G-Audio/lib/g_audio_32.dll"/>
<Item Name="lvanlys.dll" Type="Document" URL="/&lt;resource&gt;/lvanlys.dll"/>
<Item Name="lvsound2.dll" Type="Document" URL="/&lt;resource&gt;/lvsound2.dll"/>
</Item>
<Item Name="Build Specifications" Type="Build"/>
</Item>
</Project>

Some files were not shown because too many files have changed in this diff Show More