Skip to content

Commit

Permalink
Import the pypitch source code from the old upstream git.
Browse files Browse the repository at this point in the history
  • Loading branch information
stump committed Jul 13, 2010
1 parent ab5c959 commit 40f33fa
Show file tree
Hide file tree
Showing 8 changed files with 720 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/pypitch/AnalyzerInput.cpp
@@ -0,0 +1,36 @@
/*
* pypitch - analyze audio streams for pitch
* Copyright (C) 2009 John Stumpo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* $Id$ */

#include <Python.h>

#include "AnalyzerInput.hpp"

PyObject* feedAnalyzer(Analyzer* a, PyObject* instr)
{
float* a_input;

if (!PyString_Check(instr))
return PyErr_Format(PyExc_TypeError, "a string is required");

a_input = (float*)PyString_AsString(instr);
a->input(a_input, a_input + (PyString_Size(instr) / sizeof(float)));

Py_RETURN_NONE;
}
28 changes: 28 additions & 0 deletions src/pypitch/AnalyzerInput.hpp
@@ -0,0 +1,28 @@
/*
* pypitch - analyze audio streams for pitch
* Copyright (C) 2009 John Stumpo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* $Id$ */

#ifndef ANALYZERINPUT_HPP
#define ANALYZERINPUT_HPP

#include "pitch.hpp"

PyObject* feedAnalyzer(Analyzer* a, PyObject* instr);

#endif
19 changes: 19 additions & 0 deletions src/pypitch/__init__.py
@@ -0,0 +1,19 @@
# pypitch - analyze audio streams for pitch
# Copyright (C) 2008-2009 John Stumpo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

__version__ = '$Id$'

from _pypitch import *
87 changes: 87 additions & 0 deletions src/pypitch/_pypitch.pyx
@@ -0,0 +1,87 @@
# pypitch - analyze audio streams for pitch
# Copyright (C) 2008-2009 John Stumpo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

__version__ = '$Id$'

cdef extern from "vector":
ctypedef struct _DoubleVector 'std::vector<double>':
double (*get 'operator[]' )(int) nogil
int (*size)() nogil

cdef extern from "pitch.hpp":
ctypedef struct _Tone 'const Tone':
double freq
double db
double stabledb
double* harmonics
int age
ctypedef struct _Analyzer 'Analyzer':
void (*process)() nogil
double (*getPeak)() nogil
_DoubleVector (*getFormants)() nogil
_Tone* (*findTone)(double, double) nogil
_Analyzer* new_Analyzer 'new Analyzer' (double) nogil
void delete_Analyzer 'delete' (_Analyzer*) nogil

cdef extern from "AnalyzerInput.hpp":
object feedAnalyzer(_Analyzer*, object)

class Tone:
def __init__(self, freq, db, stabledb, harmonics, age):
self.freq = freq
self.db = db
self.stabledb = stabledb
self.harmonics = harmonics
self.age = age

cdef object PyTone_FromTone(_Tone* t):
cdef int i
if t == NULL:
return None
harmonics = []
for 0 <= i < 8:
harmonics.append(t.harmonics[i])
return Tone(t.freq, t.db, t.stabledb, harmonics, t.age)

cdef class Analyzer:
cdef _Analyzer* _this
def __cinit__(self, double rate):
self._this = new_Analyzer(rate)
def __dealloc__(self):
delete_Analyzer(self._this)
def input(self, instr):
if not typecheck(instr, str):
instr = instr.tostring() # assume it was a numpy array
return feedAnalyzer(self._this, instr)
def process(self):
self._this.process()
def getPeak(self):
return self._this.getPeak()
def getFormants(self):
cdef _DoubleVector v
cdef int i
cdef double cur
v = self._this.getFormants()
formants = []
for 0 <= i < v.size():
cur = v.get(i)
if cur == 0.0:
formants.append(None)
else:
formants.append(cur)
return formants
def findTone(self, double minfreq=70.0, double maxfreq=700.0):
return PyTone_FromTone(self._this.findTone(minfreq, maxfreq))
123 changes: 123 additions & 0 deletions src/pypitch/fft.hpp
@@ -0,0 +1,123 @@
/* This file is copied from /libda/fft.hpp in the source code for Performous.
*
* Performous is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Performous is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Performous; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef AUDIO_FFT_HPP_INCLUDED
#define AUDIO_FFT_HPP_INCLUDED

/**
@file fft.hpp FFT and related facilities.
Header only, no need to link with libda.
**/

#include <complex>
#include <cstddef>

namespace da {

namespace math {

/** Calculate the square of val. **/
static inline double sqr(double val) { return val * val; }

template <unsigned M, unsigned N, unsigned B, unsigned A> struct SinCosSeries {
static double value() {
return 1 - sqr(A * M_PI / B) / M / (M+1) * SinCosSeries<M + 2, N, B, A>::value();
}
};
template <unsigned N, unsigned B, unsigned A> struct SinCosSeries<N, N, B, A> {
static double value() { return 1.0; }
};

template <unsigned A, unsigned B> struct Sin {
static double value() { return (A * M_PI / B) * SinCosSeries<2, 34, B, A>::value(); }
};

template <unsigned A, unsigned B> struct Cos {
static double value() { return SinCosSeries<1, 33, B, A>::value(); }
};

/** Calculate sin(2 pi A / B). **/
template <unsigned A, unsigned B> double sin() { return Sin<A, B>::value(); }

/** Calculate cos(2 pi A / B). **/
template <unsigned A, unsigned B> double cos() { return Cos<A, B>::value(); }
}

namespace fourier {
// Based on the description of Volodymyr Myrnyy in
// http://www.dspdesignline.com/showArticle.jhtml?printableArticle=true&articleId=199903272
template<unsigned P, typename T> struct DanielsonLanczos {
static void apply(std::complex<T>* data) {
const std::size_t N = 1 << P;
const std::size_t M = N / 2;
// Compute even and odd halves
DanielsonLanczos<P - 1, T>().apply(data);
DanielsonLanczos<P - 1, T>().apply(data + M);
// Combine the results
using math::sqr;
using math::sin;
const std::complex<T> wp(-2.0 * sqr(sin<1, N>()), -sin<2, N>());
std::complex<T> w(1.0);
for (std::size_t i = 0; i < M; ++i) {
std::complex<T> temp = data[i + M] * w;
data[M + i] = data[i] - temp;
data[i] += temp;
w += w * wp;
}
}
};

template<typename T> struct DanielsonLanczos<0, T> { static void apply(std::complex<T>*) {} };
}

/** Perform FFT on data. **/
template<unsigned P, typename T> void fft(std::complex<T>* data) {
// Perform bit-reversal sorting of sample data.
const std::size_t N = 1 << P;
std::size_t j = 0;
for (std::size_t i = 0; i < N; ++i) {
if (i < j) std::swap(data[i], data[j]);
std::size_t m = N / 2;
while (m > 1 && m <= j) { j -= m; m >>= 1; }
j += m;
}
// Do the actual calculation
fourier::DanielsonLanczos<P, T>::apply(data);
}

/** Perform FFT on data from floating point iterator, windowing the input. **/
template<unsigned P, typename InIt, typename Window> std::vector<std::complex<float> > fft(InIt begin, Window window) {
std::vector<std::complex<float> > data(1 << P);
// Perform bit-reversal sorting of sample data.
const std::size_t N = 1 << P;
std::size_t j = 0;
for (std::size_t i = 0; i < N; ++i) {
data[j] = *begin++ * window[i];
std::size_t m = N / 2;
while (m > 1 && m <= j) { j -= m; m >>= 1; }
j += m;
}
// Do the actual calculation
fourier::DanielsonLanczos<P, float>::apply(&data[0]);
return data;
}

}

#endif

0 comments on commit 40f33fa

Please sign in to comment.