问题
I basically have some source-code(not my own) in python that I would like to understand. It's an anti-aliased xor audio oscillator. I don't know python at all - but it's quite readable except for a few things:
Firstly - the full code:
f0 = 500.
fs = 44100.
T0 = f0/fs
P0 = fs/f0
t = arange(0,3*fs)
L = len(t)
imax = 2**16
# =============================================================================
# SIGNALS
# =============================================================================
# -----------------------------------------------------------------------------
#
def trivial_xor():
s = zeros(L)
sd1 = zeros(L)
sd2 = zeros(L)
s = zeros(L)
w = 0.5
p = 0
for n in range(0,L):
d1 = 2*p - 1
if p < w: d2 = 0
else: d2 = -0.5
x1 = int(d1 * imax) & 0xFFFF
x2 = int(d2 * imax) & 0xFFFF
y = (x1 ^ x2) / float(imax)
s[n] = 2*y - 1
sd1[n] = d1
sd2[n] = d2
p += T0
if p > 1: p -= 1
return s
# -----------------------------------------------------------------------------
#
def trivial_xor_withSources():
s = zeros(L)
sd1 = zeros(L)
sd2 = zeros(L)
s = zeros(L)
w = 0.5
p = 0
for n in range(0,L):
d1 = 2*p - 1
if p < w: d2 = 0
else: d2 = -0.5
x1 = int(d1 * imax) & 0xFFFF
x2 = int(d2 * imax) & 0xFFFF
y = (x1 ^ x2) / float(imax)
s[n] = 2*y - 1
sd1[n] = d1
sd2[n] = d2
p += T0
if p > 1: p -= 1
return s,sd1,sd2
# -----------------------------------------------------------------------------
#
def PTR1_xor():
s = trivial_xor() - 2*T0
#
T1 = 2*T0
P1 = 1/T1
cdc = 1 + T1
p0 = p1 = 0
#
for n in range(0,L):
if p0 < 0.5:
h = 0.5
if p1 < T1:
s[n] = p1*(2 - 2*h*P1) + 2*h - cdc
elif p0 < 0.75:
h = 0.5
if p1 < T1:
s[n] = p1*(2 - 2*h*P1) + 2*h - cdc + 1
else:
h = 1
pp = p1 - 0.5
if pp < T1:
s[n] = pp*(2 - 2*h*P1) + 2*h - cdc
#
p0 += T0
p1 += T1
if p0 > 1: p0 -= 1
if p1 > 1: p1 -= 1
return s
It all seems pretty straight forward - except for what I assume to be the buffers, all I need to know is what is these function(s) in c++?
////////////////////////////////
t = arange(0,3*fs)
L = len(t)
imax = 2**16
////////////////////////////////
def trivial_xor_withSources():
s = zeros(L)
sd1 = zeros(L)
sd2 = zeros(L)
s = zeros(L)
w = 0.5
p = 0
for n in range(0,L):
I'm planning on using this in real time. The rest just look like simple math. Any help greatly appreciated!
Andrew
回答1:
If you're trying to convert the code to C++, you can easily implement a (roughly) equivalent arange
function:
#include <vector>
template<typename T>
std::vector<T> arange(T start, T stop, T step = 1) {
std::vector<T> values;
for (T value = start; value < stop; value += step)
values.push_back(value);
return values;
}
You could then use it like this:
auto t = arange<double>(0, 3*fs);
auto L = t.length();
The **
is exponentiation. You could call the pow
function:
#include <cmath>
const double imax = pow(2., 16.);
But since you are dealing with constants anyway, you would be better off with:
const double imax = 65536.;
If you want to retain the expressive power of 2**16
and you don't want to incur the run-time cost of calling pow
(perhaps you want to be able to change the exponent without having to manually recalculate the constant), you can use a constexpr
function:
constexpr unsigned long power(unsigned long base, unsigned long exponent) {
return exponent == 0 ? 1 : base * pow(base, exponent - 1);
}
const unsigned long imax = power(2, 16);
回答2:
Here is an explanation for all the non-trivials lines you outlined:
len(t)
means "length oft
", that is to say, the number of elements in array t.2**16
is "two to the power of 16" (1 << 16
in your C++ code).for n in range(0,L)
is equivalent tofor (int n = 0; i < L; ++i)
arange
andzeros
are likely Numpy functions. You can find reference for them here and here.
Regarding the last point, probably there is some import
statement you omitted from the code.
Quoting from the docs:
arange
Return evenly spaced values within a given interval.
Values are generated within the half-open interval [start, stop) (in other words, the interval including start but excluding stop).
The default step is 1
, so t
will be an array containing numbers [0, 1, 2, 3, ..., 3 * 44100 - 1]
.
zeros
Return a new array of given shape and type, filled with zeros.
Default type for zeros
is float
, so s
, sd1
and sd2
are initialized as arrays filled of 0.0
, each having L
elements.
回答3:
Python: t = arange(0,3*fs)
C++: double t[] = {0.0,1.0,...,3*fs}; // will not compile of course
Python: L = len(t)
C++: int L = sizeof(t)/sizeof(*t); // where t is an array in the current scope
Python: s = zeros(L)
C++: double s[L] = {0}; // where L is a constant
Python: for n in range(0,L)
C++: for (int i=0; i<L; i++)
来源:https://stackoverflow.com/questions/21216909/these-python-functions-in-c