Skip to content

Commit

Permalink
Merge pull request #39 from wtq2255/master
Browse files Browse the repository at this point in the history
Update 0.1.9
  • Loading branch information
wtq2255 authored May 24, 2024
2 parents 6d41b13 + f7e347f commit 57e97b3
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 6 deletions.
2 changes: 1 addition & 1 deletion conda/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set version = "0.1.8" %}
{% set version = "0.1.9" %}

package:
name: audioflux
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
ChangeLog
=========
v0.1.9
------
* New features:
* Add `audioflux.utils.synth_f0`.
* Fix bug:
* `#37 <https://github.com/libAudioFlux/audioFlux/issues/37>`__: Fix `audioflux.display.fill_spec` bug.

v0.1.8
------
* New features:
Expand Down
1 change: 1 addition & 0 deletions docs/utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Utils
audioflux.utils.midi_to_hz
audioflux.utils.hz_to_note
audioflux.utils.hz_to_midi
audioflux.utils.synth_f0

Sample
------
Expand Down
2 changes: 1 addition & 1 deletion python/audioflux/__version__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__title__ = 'audioflux'
__description__ = 'A library for audio and music analysis, feature extraction.'
__version__ = '0.1.8'
__version__ = '0.1.9'
9 changes: 7 additions & 2 deletions python/audioflux/display/display.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import warnings

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.axes as plaxes
from matplotlib import colormaps
from matplotlib.ticker import Formatter, ScalarFormatter, MaxNLocator, SymmetricalLogLocator, FixedLocator
from audioflux.utils import midi_to_note

Expand Down Expand Up @@ -190,7 +190,12 @@ def fill_spec(
if y_axis == 'chroma':
y_coords = np.arange(data.shape[-2] + 1)

cmap = colormaps['plasma']
if hasattr(mpl, 'colormaps'):
cmap = mpl.colormaps['plasma']
else:
from matplotlib.cm import get_cmap
cmap = get_cmap('plasma')

collection = axes.pcolormesh(x_coords, y_coords, data, cmap=cmap)

axes.set_xlim(np.min(x_coords), np.max(x_coords))
Expand Down
1 change: 1 addition & 0 deletions python/audioflux/mir/pitch_yin.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class PitchYIN(Base):
>>> fre_arr, v1_arr, v2_arr = pitch_obj.pitch(audio_arr)
Show pitch plot
>>> import matplotlib.pyplot as plt
>>> times = np.arange(fre_arr.shape[-1]) * (pitch_obj.slide_length / sr)
>>> fig, ax = plt.subplots(nrows=2, sharex=True)
Expand Down
79 changes: 78 additions & 1 deletion python/audioflux/utils/util.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import warnings
import numpy as np
from ctypes import c_int, c_float, c_void_p, POINTER

from audioflux.fftlib import get_fft_lib

__all__ = [
'ascontiguous_T',
'ascontiguous_swapaxex',
'format_channel',
'revoke_channel',
'check_audio',
'check_audio_length'
'check_audio_length',
'synth_f0'
]


Expand Down Expand Up @@ -104,3 +108,76 @@ def check_audio_length(X, radix2_exp):
f'only the first fft_length={fft_length} data are valid')
X = X[..., :fft_length].copy()
return X


def synth_f0(times, frequencies, samplate, amplitudes=None):
"""
Generate an audio array based on the frequency f0.
Parameters
----------
times: ndarray [shape=(n)]
Time points for each frequency, in seconds.
frequencies: ndarray [shape=(n)]
Array of frequencies, in Hz.
samplate: int
The output sampling rate.
amplitudes: ndarray [shape=(n)]
The amplitude of each frequency, ranging from 0 to 1.
Default is None, which means that the amplitude is 1. Like: `np.ones((n,))`
Returns
-------
out: ndarray
Return the audio array generated based on the frequencies
Examples
--------
>>> import audioflux as af
>>> import numpy as np
>>> f0_arr = np.ones((1024,)) * 220
>>> times = np.arange(0, f0_arr.shape[0]) * (1024 / 32000)
>>> amplitude_arr = np.ones_like(f0_arr) * 0.4
>>> audio_arr = af.utils.synth_f0(times, f0_arr, 32000, amplitude_arr)
"""
times = np.asarray(times, dtype=np.float32, order='C')
if times.ndim != 1:
raise ValueError(f"times[ndim={times.ndim}] must be a 1D array")

frequencies = np.asarray(frequencies, dtype=np.float32, order='C')
if frequencies.ndim != 1:
raise ValueError(f"frequencies[ndim={frequencies.ndim}] must be a 1D array")

if times.shape[0] != frequencies.shape[0]:
raise ValueError(f"The lengths of times and frequencies must be the same.")

if amplitudes is not None:
amplitudes = np.asarray(amplitudes, dtype=np.float32, order='C')
if amplitudes.ndim != 1:
raise ValueError(f"amplitudes[ndim={amplitudes.ndim}] must be a 1D array")

if amplitudes.shape[0] != frequencies.shape[0]:
raise ValueError(f"The lengths of amplitudes and frequencies must be the same.")

fn = get_fft_lib()['util_synthF0']
fn.argtypes = [
np.ctypeslib.ndpointer(dtype=np.float32, ndim=1, flags='C_CONTIGUOUS'),
np.ctypeslib.ndpointer(dtype=np.float32, ndim=1, flags='C_CONTIGUOUS'),
c_int, c_int,
POINTER(c_void_p) if amplitudes is None else np.ctypeslib.ndpointer(dtype=np.float32, ndim=1, flags='C_CONTIGUOUS'),
]
fn.restype = c_void_p

length = times.shape[0]
length1 = round(np.max(times) * samplate)

p = fn(times, frequencies, c_int(length), c_int(samplate), amplitudes)
ret = np.frombuffer((c_float * length1).from_address(p), np.float32).copy()
return ret
2 changes: 1 addition & 1 deletion src/util/flux_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void util_delta(float *dataArr1,int length,int order,float *dataArr2);
void util_preEmphasis(float *vArr1,int length,float coef,float *vArr2);

// synthesized f0; length1=floor(time*fs), ampArr can NULL, default is 1
float *util_synthF0(float *timeArr,float *freArr,int samplate,int length,float *ampArr);
float *util_synthF0(float *timeArr,float *freArr,int length,int samplate,float *ampArr);

// wave
int util_readWave(char *name,float **dataArr);
Expand Down

0 comments on commit 57e97b3

Please sign in to comment.