Metadata-Version: 2.4
Name: abletonparsing
Version: 0.1.3
Summary: Python module for parsing Ableton Live ASD clip files containing warp markers.
Home-page: https://github.com/DBraun/AbletonParsing
Author: David Braun
Author-email: braun@ccrma.stanford.edu
Project-URL: Bug Tracker, https://github.com/DBraun/AbletonParsing/issues
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: librosa; extra == "test"
Requires-Dist: soundfile; extra == "test"
Requires-Dist: pyrubberband; extra == "test"
Dynamic: license-file

# AbletonParsing

[![CI](https://github.com/DBraun/AbletonParsing/actions/workflows/ci.yml/badge.svg)](https://github.com/DBraun/AbletonParsing/actions/workflows/ci.yml)
[![PyPI version](https://badge.fury.io/py/abletonparsing.svg)](https://badge.fury.io/py/abletonparsing)

Parse an Ableton ASD clip file and its warp markers in Python. This module has been tested with `.asd` files saved with Ableton 9 and Ableton 10. 

**Note:** Ableton Live 12 uses a different binary format that is not yet supported by this library.

## Install

`pip install abletonparsing`

### Development Dependencies

To run the tests, you'll need to install additional dependencies:

```bash
# On macOS
brew install rubberband

# On Ubuntu/Debian
sudo apt-get install -y rubberband-cli

# Install Python test dependencies
pip install abletonparsing[test]
# or
pip install -e ".[test]"  # for development
```

## API

Clip class:
* .loop_on - ( bool , READ/WRITE ) - Loop toggle is on
* .start_marker - ( float , READ/WRITE ) - Start marker in beats relative to 1.1.1
* .end_marker - ( float , READ/WRITE ) - End marker in beats relative to 1.1.1
* .loop_start - ( float , READ/WRITE ) - Loop start in beats relative to 1.1.1
* .loop_end - ( float , READ/WRITE ) - Loop end in beats relative to 1.1.1
* .hidden_loop_start - ( float , READ/WRITE ) - Hidden loop start in beats relative to 1.1.1
* .hidden_loop_end - ( float , READ/WRITE ) - Hidden loop end in beats relative to 1.1.1
* .warp_markers - ( list[WarpMarker] , READ/WRITE ) - List of warp markers
* .warp_on - ( bool , READ/WRITE ) - Warping is on
* .sr - ( float , READ/WRITE ) - Sample rate of audio data

WarpMarker class:
* .seconds - ( float , READ/WRITE ) - Position in seconds in the audio data.
* .beats - ( float , READ/WRITE ) - Position in "beats" (typically quarter note) relative to 1.1.1

If `loop_on` is false, then `loop_start` will equal the `start_marker`, and `loop_end` will equal the `end_marker`.

## Example

```python
import abletonparsing

import librosa
import soundfile as sf
import pyrubberband as pyrb

bpm = 130.
audio_path = 'drums.wav'
clip_path = audio_path + '.asd'

audio_data, sr = librosa.load(audio_path, sr=None, mono=False)
num_samples = audio_data.shape[1]

clip = abletonparsing.Clip(clip_path, sr, num_samples)

time_map = clip.get_time_map(bpm)

# Time-stretch the audio to the requested bpm.
output_audio = pyrb.timemap_stretch(audio_data.transpose(), sr, time_map)

with sf.SoundFile('output.wav', 'w', sr, 2, 'PCM_24') as f:
	f.write(output_audio)
```
