music.pan_transitions

music.pan_transitions(p=((1, 1), (1, 0), (0, 1), (1, 1)), d=(2, 2, 2), method=('lin', 'circ', 'exp'), sample_rate=44100, sonic_vector=None)[source]

Applies pan transitions to a sonic vector.

Parameters:
plist of tuples, optional

List of pan positions, where each tuple represents the amplitude envelope of each channel, by default [(1,1),(1,0),(0,1),(1,1)]

dlist, optional

List of durations for each transition, by default [2,2,2]

methodlist, optional

List of pan transition methods, by default [‘lin’,’circ’,’exp’]

sample_rateint, optional

Sample rate of the audio, by default 44100

sonic_vectorndarray, optional

A mono or stereo sound to pan. Without one, the two envelopes themselves are returned.

Returns:
ndarray

The (2, n) panning envelopes, or sonic_vector scaled by them: as long as the sound, holding the last position past the end of the transitions.

Notes

Each pan transition i starts and ends amplitude envelope of channel c in p[i][c] and p[i+1][c].

method is accepted and not read. The three laws below say what each would do; the body interpolates linearly whatever it is given, so ‘lin’, ‘circ’ and ‘exp’ all render the same ramp. tests/test_artifacts.py pins that, so implementing them is a deliberate change rather than a surprise.

Consider only one of such fades to understand the pan transition methods:

'lin' fades linearly in and out:
    x*k_i+y*(1-k_i)
    or
    s1_i*x_i +s2_i*(1-x_i) = (s1-s2)*x_i + s_2
'circ' keeps amplitude one using
    cos(x)**2 + sin(y)**2 = 1
'exp' makes the cross_fade using exponentials.

‘exp’ entails linear loudness variation for each channel, but total loudness is not preserved because final amplitude’s ambit is not preserved. ‘lin’ and ‘circ’, on the other hand, preserve total loudness but does not provide a linear variation of loudness for each sound on the cross-fade.

For now, each channel’s signal are kept from mixing. One immediate possibility is to maintain the expected tessitura of the sample amplitudes. Say p = [.5,1,0,.5] ~ [(1,1),(1,0),(0,1),(1,1)]. Then pi,pj = .5,1 might be performed as:

s1 = s1*.5 -> 0
s2 = s1*.5 -> (s1+s2)*.5

Or through sinusoids and exponentials

Make fast and slow fades and parameter transitions using weber-fechner and steven’s laws. E.g.:

pitch_trans = [pitch0*X**(i/Y) for i in range(12)]
pitch_trans = [pitch0 + X*i**Y for i in range(12)]

Examples

>>> p = [(0, 1), (1, 0), (0, 1), (1, 1)]
>>> d = [2, 2, 2]
>>> method = ['lin', 'circ', 'exp']
>>> sonic_vector = np.random.rand(2, 44100 * 6)  # Random stereo signal
>>> result = pan_transitions(p, d, method, sonic_vector=sonic_vector)