Skip to content

Commit

Permalink
Merge pull request #10 from HEnquist/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
HEnquist committed Dec 19, 2020
2 parents 278ea74 + 36d3667 commit 8e7400e
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 13 deletions.
56 changes: 46 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# pyCamillaDSP
Companion Python library for CamillaDSP.
Works with CamillaDSP version 0.4.0 and up.
Works with CamillaDSP version 0.5.0 and up.

Download the library, either by `git clone` or by downloading a zip file of the code. Then unpack the files, go to the folder containing the `setup.py` file and run:
```sh
Expand Down Expand Up @@ -78,7 +78,9 @@ except IOError as e:

## Methods

The CamillaConnection class provides the following methods:
The CamillaConnection class provides the following methods

### Basics

| Method | Description |
|----------|---------------|
Expand All @@ -88,15 +90,13 @@ The CamillaConnection class provides the following methods:
|`get_version()` | Read CamillaDSP version, returns a tuple with 3 elements|
|`get_library_version()` | Read pyCamillaDSP version, returns a tuple with 3 elements|
|`get_state()` | Get current processing state. Returns one of "RUNNING", "PAUSED" or "INACTIVE".|
|`get_signal_range()` | Get current signal range.|
|`get_signal_range_dB()` | Get current signal range in dB.|
|`get_capture_rate_raw()` | Get current capture rate, raw value.|
|`get_capture_rate()` | Get current capture rate. Returns the nearest common value.|
|`get_update_interval()` | Get current update interval in ms.|
|`set_update_interval(value)` | Set current update interval in ms.|
|`get_rate_adjust()` | Get current value for rate adjust.|
|`stop()` | Stop processing and wait for new config if wait mode is active, else exit. |
|`exit()` | Stop processing and exit.|


### Config handling
| Method | Description |
|----------|---------------|
|`reload()` | Reload config from disk.|
|`get_config_name()` | Get path to current config file.|
|`set_config_name(value)` | Set path to config file.|
Expand All @@ -108,10 +108,46 @@ The CamillaConnection class provides the following methods:
|`read_config_file(path)` | Read a config file from `path`. Returns the loaded config with all optional fields filled with defaults. Raises a CamillaError on errors.|
|`read_config(config)` | Read a config from yaml string and return the contents as an obect, with defaults filled out with their default values.|

### Reading status
| Method | Description |
|----------|---------------|
|`get_signal_range()` | Get current signal range.|
|`get_signal_range_dB()` | Get current signal range in dB.|
|`get_capture_signal_rms()` | Get capture signal level rms in dB. Full scale is 0 dB. Returns a list with one element per channel.|
|`get_playback_signal_rms()` | Get playback signal level rms in dB. Full scale is 0 dB. Returns a list with one element per channel.|
|`get_capture_signal_peak()` | Get capture signal level peak in dB. Full scale is 0 dB. Returns a list with one element per channel.|
|`get_playback_signal_peak()` | Get playback signal level peak in dB. Full scale is 0 dB. Returns a list with one element per channel.|
|`get_capture_rate_raw()` | Get current capture rate, raw value.|
|`get_capture_rate()` | Get current capture rate. Returns the nearest common value.|
|`get_update_interval()` | Get current update interval in ms.|
|`set_update_interval(value)` | Set current update interval in ms.|
|`get_rate_adjust()` | Get current value for rate adjust.|
|`get_buffer_level()` | Get current buffer level of the playback device.|
|`get_clipped_samples()` | Get number of clipped samples since the config was loaded.|

### Volume control
| Method | Description |
|----------|---------------|
|`get_volume()` | Get current volume setting in dB.|
|`set_volume(value)` | Set volume in dB.|

# Included examples:

play_wav: Play a wav file. This example reads a configuration from a file, updates the capture device fto point at a given .wav file, and sends this modified config to CamillaDSP.
## read_rms
Read the playback signal level continuously and print in the terminal, until stopped by Ctrl+c.
```sh
python read_rms.py 1234
```

## set_volume
Set the volume control to a new value. First argument is websocket port, second is new volume in dB.
For this to work, CamillaDSP must be running a configuration that has Volume filters in the pipeline for every channel.
```sh
python set_volume.py 1234 -12.3
```

## play_wav
Play a wav file. This example reads a configuration from a file, updates the capture device fto point at a given .wav file, and sends this modified config to CamillaDSP.
Usage example:
```sh
python play_wav.py 1234 /path/to/wavtest.yml /path/to/music.wav
Expand Down
49 changes: 47 additions & 2 deletions camilladsp/camilladsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import math
from threading import Lock

VERSION = (0, 4, 1)
VERSION = (0, 5, 0)

STANDARD_RATES = [
8000,
Expand Down Expand Up @@ -48,7 +48,7 @@ def __init__(self, host, port):

def _query(self, command, arg=None):
if self._ws is not None:
if arg:
if arg is not None:
query = json.dumps({command: arg})
else:
query = json.dumps(command)
Expand Down Expand Up @@ -152,6 +152,51 @@ def get_signal_range_dB(self):
range_dB = -1000
return range_dB

def get_capture_signal_rms(self):
"""
Get capture signal level rms in dB. Full scale is 0 dB. Returns a list with one element per channel.
"""
sigrms = self._query("GetCaptureSignalRms")
sigrms = [float(val) for val in sigrms]
return sigrms

def get_playback_signal_rms(self):
"""
Get playback signal level rms in dB. Full scale is 0 dB. Returns a list with one element per channel.
"""
sigrms = self._query("GetPlaybackSignalRms")
sigrms = [float(val) for val in sigrms]
return sigrms

def get_capture_signal_peak(self):
"""
Get capture signal level peak in dB. Full scale is 0 dB. Returns a list with one element per channel.
"""
sigpeak = self._query("GetCaptureSignalPeak")
sigpeak = [float(val) for val in sigpeak]
return sigpeak

def get_playback_signal_peak(self):
"""
Get playback signal level peak in dB. Full scale is 0 dB. Returns a list with one element per channel.
"""
sigpeak = self._query("GetPlaybackSignalPeak")
sigpeak = [float(val) for val in sigpeak]
return sigpeak

def get_volume(self):
"""
Get current volume setting in dB.
"""
vol = self._query("GetVolume")
return float(vol)

def set_volume(self, value):
"""
Set volume in dB.
"""
self._query("SetVolume", arg=float(value))

def get_capture_rate_raw(self):
"""
Get current capture rate, raw value.
Expand Down
22 changes: 22 additions & 0 deletions examples/read_rms/read_rms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# play wav
from camilladsp import CamillaConnection
import sys
import time

try:
port = int(sys.argv[1])
except:
print("Usage: start CamillaDSP with the socketserver enabled:")
print("> camilladsp -p4321 yourconfig.yml")
print("Then read the signal level")
print("> python read_rms.py 4321")
sys.exit()

cdsp = CamillaConnection("127.0.0.1", port)
cdsp.connect()

print("Reading playback signal RMS, press Ctrl+c to stop")
while True:
print(cdsp.get_playback_signal_rms())
time.sleep(1)

24 changes: 24 additions & 0 deletions examples/set_volume/set_volume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# play wav
from camilladsp import CamillaConnection
import sys
import time

try:
port = int(sys.argv[1])
new_vol = float(sys.argv[2])
except:
print("Usage: Make sure that your pipeline includes Volume filters for each channel.")
print("Then start CamillaDSP with the websocket server enabled:")
print("> camilladsp -p4321 yourconfig.yml")
print("Then set the volume")
print("> python read_rms.py 4321 -12.3")
sys.exit()

cdsp = CamillaConnection("127.0.0.1", port)
cdsp.connect()

current_vol = cdsp.get_volume()
print(f"Current volume: {current_vol} dB")
print(f"Changing volume to: {new_vol} dB")
cdsp.set_volume(new_vol)

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="camilladsp",
version="0.4.1",
version="0.5.0",
author="Henrik Enquist",
author_email="henrik.enquist@gmail.com",
description="A library for comminucating with CamillaDSP",
Expand Down
18 changes: 18 additions & 0 deletions tests/test_camillaws.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def __init__(self):
'"GetState"': json.dumps({"GetState": {"result": "Ok", "value": "IDLE"}}),
'"GetVersion"': json.dumps({"GetVersion": {"result": "Ok", "value": "0.3.2"}}),
'"GetSignalRange"': json.dumps({"GetSignalRange": {"result": "Ok", "value": "0.2"}}),
'"GetCaptureSignalRms"': json.dumps({"GetCaptureSignalRms": {"result": "Ok", "value": [0.1, 0.2]}}),
'"GetCaptureRate"': json.dumps({"GetCaptureRate": {"result": "Ok", "value": "88250"}}),
'"GetErrorValue"': json.dumps({"GetErrorValue": {"result": "Error", "value": "badstuff"}}),
'"GetError"': json.dumps({"GetError": {"result": "Error"}}),
Expand Down Expand Up @@ -94,6 +95,10 @@ def test_signal_range(camilla_mockws):
camilla_mockws.connect()
assert camilla_mockws.get_signal_range() == 0.2

def test_signal_rms(camilla_mockws):
camilla_mockws.connect()
assert camilla_mockws.get_capture_signal_rms() == [0.1, 0.2]

def test_signal_range_dB(camilla_mockws):
camilla_mockws.connect()
assert camilla_mockws.get_signal_range_dB() == -20
Expand Down Expand Up @@ -168,6 +173,19 @@ def test_queries(camilla_mockquery):
camilla_mockquery._query.assert_called_with('GetBufferLevel')
camilla_mockquery.get_clipped_samples()
camilla_mockquery._query.assert_called_with('GetClippedSamples')
camilla_mockquery.get_volume()
camilla_mockquery._query.assert_called_with('GetVolume')
camilla_mockquery.set_volume(-25.0)
camilla_mockquery._query.assert_called_with('SetVolume', arg=-25.0)
camilla_mockquery.get_capture_signal_rms()
camilla_mockquery._query.assert_called_with('GetCaptureSignalRms')
camilla_mockquery.get_capture_signal_peak()
camilla_mockquery._query.assert_called_with('GetCaptureSignalPeak')
camilla_mockquery.get_playback_signal_rms()
camilla_mockquery._query.assert_called_with('GetPlaybackSignalRms')
camilla_mockquery.get_playback_signal_peak()
camilla_mockquery._query.assert_called_with('GetPlaybackSignalPeak')


def test_queries_adv(camilla_mockquery_yaml):
camilla_mockquery_yaml.read_config_file("some/path")
Expand Down

0 comments on commit 8e7400e

Please sign in to comment.