mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-03 14:17:12 +00:00
Add speechPlayer Klatt implementation as Klatt 6.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYER_H
|
||||
#define SPEECHPLAYER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef double speechPlayer_frameParam_t;
|
||||
|
||||
typedef struct {
|
||||
// voicing and cascaide
|
||||
speechPlayer_frameParam_t voicePitch; // fundermental frequency of voice (phonation) in hz
|
||||
speechPlayer_frameParam_t vibratoPitchOffset; // pitch is offset up or down in fraction of a semitone
|
||||
speechPlayer_frameParam_t vibratoSpeed; // Speed of vibrato in hz
|
||||
speechPlayer_frameParam_t voiceTurbulenceAmplitude; // amplitude of voice breathiness from 0 to 1
|
||||
speechPlayer_frameParam_t glottalOpenQuotient; // fraction between 0 and 1 of a voice cycle that the glottis is open (allows voice turbulance, alters f1...)
|
||||
speechPlayer_frameParam_t voiceAmplitude; // amplitude of voice (phonation) source between 0 and 1.
|
||||
speechPlayer_frameParam_t aspirationAmplitude; // amplitude of aspiration (voiceless h, whisper) source between 0 and 1.
|
||||
speechPlayer_frameParam_t cf1, cf2, cf3, cf4, cf5, cf6, cfN0, cfNP; // frequencies of standard cascaide formants, nasal (anti) 0 and nasal pole in hz
|
||||
speechPlayer_frameParam_t cb1, cb2, cb3, cb4, cb5, cb6, cbN0, cbNP; // bandwidths of standard cascaide formants, nasal (anti) 0 and nasal pole in hz
|
||||
speechPlayer_frameParam_t caNP; // amplitude from 0 to 1 of cascade nasal pole formant
|
||||
// fricatives and parallel
|
||||
speechPlayer_frameParam_t fricationAmplitude; // amplitude of frication noise from 0 to 1.
|
||||
speechPlayer_frameParam_t pf1, pf2, pf3, pf4, pf5, pf6; // parallel formants in hz
|
||||
speechPlayer_frameParam_t pb1, pb2, pb3, pb4, pb5, pb6; // parallel formant bandwidths in hz
|
||||
speechPlayer_frameParam_t pa1, pa2, pa3, pa4, pa5, pa6; // amplitude of parallel formants between 0 and 1
|
||||
speechPlayer_frameParam_t parallelBypass; // amount of signal which should bypass parallel resonators from 0 to 1
|
||||
speechPlayer_frameParam_t preFormantGain; // amplitude from 0 to 1 of all vocal tract sound (voicing, frication) before entering formant resonators. Useful for stopping/starting speech
|
||||
speechPlayer_frameParam_t outputGain; // amplitude from 0 to 1 of final output (master volume)
|
||||
speechPlayer_frameParam_t endVoicePitch; // pitch of voice at the end of the frame length
|
||||
} speechPlayer_frame_t;
|
||||
|
||||
typedef short sampleVal;
|
||||
|
||||
typedef struct {
|
||||
sampleVal value;
|
||||
} sample;
|
||||
|
||||
typedef void* speechPlayer_handle_t;
|
||||
|
||||
speechPlayer_handle_t speechPlayer_initialize(int sampleRate);
|
||||
void speechPlayer_queueFrame(speechPlayer_handle_t playerHandle, speechPlayer_frame_t* framePtr, unsigned int minFrameDuration, unsigned int fadeDuration, int userIndex, bool purgeQueue);
|
||||
int speechPlayer_synthesize(speechPlayer_handle_t playerHandle, unsigned int sampleCount, sample* sampleBuf);
|
||||
int speechPlayer_getLastIndex(speechPlayer_handle_t playerHandle);
|
||||
void speechPlayer_terminate(speechPlayer_handle_t playerHandle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <queue>
|
||||
#include "utils.h"
|
||||
#include "frame.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct frameRequest_t {
|
||||
unsigned int minNumSamples;
|
||||
unsigned int numFadeSamples;
|
||||
bool NULLFrame;
|
||||
speechPlayer_frame_t frame;
|
||||
double voicePitchInc;
|
||||
int userIndex;
|
||||
};
|
||||
|
||||
class FrameManagerImpl: public FrameManager {
|
||||
private:
|
||||
queue<frameRequest_t*> frameRequestQueue;
|
||||
frameRequest_t* oldFrameRequest;
|
||||
frameRequest_t* newFrameRequest;
|
||||
speechPlayer_frame_t curFrame;
|
||||
bool curFrameIsNULL;
|
||||
unsigned int sampleCounter;
|
||||
int lastUserIndex;
|
||||
|
||||
void updateCurrentFrame() {
|
||||
sampleCounter++;
|
||||
if(newFrameRequest) {
|
||||
if(sampleCounter>(newFrameRequest->numFadeSamples)) {
|
||||
delete oldFrameRequest;
|
||||
oldFrameRequest=newFrameRequest;
|
||||
newFrameRequest=NULL;
|
||||
} else {
|
||||
double curFadeRatio=(double)sampleCounter/(newFrameRequest->numFadeSamples);
|
||||
for(int i=0;i<speechPlayer_frame_numParams;++i) {
|
||||
((speechPlayer_frameParam_t*)&curFrame)[i]=calculateValueAtFadePosition(((speechPlayer_frameParam_t*)&(oldFrameRequest->frame))[i],((speechPlayer_frameParam_t*)&(newFrameRequest->frame))[i],curFadeRatio);
|
||||
}
|
||||
}
|
||||
} else if(sampleCounter>(oldFrameRequest->minNumSamples)) {
|
||||
if(!frameRequestQueue.empty()) {
|
||||
curFrameIsNULL=false;
|
||||
newFrameRequest=frameRequestQueue.front();
|
||||
frameRequestQueue.pop();
|
||||
if(newFrameRequest->NULLFrame) {
|
||||
memcpy(&(newFrameRequest->frame),&(oldFrameRequest->frame),sizeof(speechPlayer_frame_t));
|
||||
newFrameRequest->frame.preFormantGain=0;
|
||||
newFrameRequest->frame.voicePitch=curFrame.voicePitch;
|
||||
newFrameRequest->voicePitchInc=0;
|
||||
} else if(oldFrameRequest->NULLFrame) {
|
||||
memcpy(&(oldFrameRequest->frame),&(newFrameRequest->frame),sizeof(speechPlayer_frame_t));
|
||||
oldFrameRequest->frame.preFormantGain=0;
|
||||
}
|
||||
if(newFrameRequest) {
|
||||
if(newFrameRequest->userIndex!=-1) lastUserIndex=newFrameRequest->userIndex;
|
||||
sampleCounter=0;
|
||||
newFrameRequest->frame.voicePitch+=(newFrameRequest->voicePitchInc*newFrameRequest->numFadeSamples);
|
||||
}
|
||||
} else {
|
||||
curFrameIsNULL=true;
|
||||
}
|
||||
} else {
|
||||
curFrame.voicePitch+=oldFrameRequest->voicePitchInc;
|
||||
oldFrameRequest->frame.voicePitch=curFrame.voicePitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
FrameManagerImpl(): curFrame(), curFrameIsNULL(true), sampleCounter(0), newFrameRequest(NULL), lastUserIndex(-1) {
|
||||
oldFrameRequest=new frameRequest_t();
|
||||
oldFrameRequest->NULLFrame=true;
|
||||
}
|
||||
|
||||
void queueFrame(speechPlayer_frame_t* frame, unsigned int minNumSamples, unsigned int numFadeSamples, int userIndex, bool purgeQueue) {
|
||||
frameRequest_t* frameRequest=new frameRequest_t;
|
||||
frameRequest->minNumSamples=minNumSamples; //max(minNumSamples,1);
|
||||
frameRequest->numFadeSamples=numFadeSamples; //max(numFadeSamples,1);
|
||||
if(frame) {
|
||||
frameRequest->NULLFrame=false;
|
||||
memcpy(&(frameRequest->frame),frame,sizeof(speechPlayer_frame_t));
|
||||
frameRequest->voicePitchInc=(frame->endVoicePitch-frame->voicePitch)/frameRequest->minNumSamples;
|
||||
} else {
|
||||
frameRequest->NULLFrame=true;
|
||||
}
|
||||
frameRequest->userIndex=userIndex;
|
||||
if(purgeQueue) {
|
||||
for(;!frameRequestQueue.empty();frameRequestQueue.pop()) delete frameRequestQueue.front();
|
||||
sampleCounter=oldFrameRequest->minNumSamples;
|
||||
if(newFrameRequest) {
|
||||
oldFrameRequest->NULLFrame=newFrameRequest->NULLFrame;
|
||||
memcpy(&(oldFrameRequest->frame),&curFrame,sizeof(speechPlayer_frame_t));
|
||||
delete newFrameRequest;
|
||||
newFrameRequest=NULL;
|
||||
}
|
||||
}
|
||||
frameRequestQueue.push(frameRequest);
|
||||
}
|
||||
|
||||
const int getLastIndex() {
|
||||
return lastUserIndex;
|
||||
}
|
||||
|
||||
const speechPlayer_frame_t* const getCurrentFrame() {
|
||||
updateCurrentFrame();
|
||||
return curFrameIsNULL?NULL:&curFrame;
|
||||
}
|
||||
|
||||
~FrameManagerImpl() {
|
||||
if(oldFrameRequest) delete oldFrameRequest;
|
||||
if(newFrameRequest) delete newFrameRequest;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
FrameManager* FrameManager::create() { return new FrameManagerImpl(); }
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYER_FRAME_H
|
||||
#define SPEECHPLAYER_FRAME_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
typedef double speechPlayer_frameParam_t;
|
||||
|
||||
typedef struct {
|
||||
// voicing and cascaide
|
||||
speechPlayer_frameParam_t voicePitch; // fundermental frequency of voice (phonation) in hz
|
||||
speechPlayer_frameParam_t vibratoPitchOffset; // pitch is offset up or down in fraction of a semitone
|
||||
speechPlayer_frameParam_t vibratoSpeed; // Speed of vibrato in hz
|
||||
speechPlayer_frameParam_t voiceTurbulenceAmplitude; // amplitude of voice breathiness from 0 to 1
|
||||
speechPlayer_frameParam_t glottalOpenQuotient; // fraction between 0 and 1 of a voice cycle that the glottis is open (allows voice turbulance, alters f1...)
|
||||
speechPlayer_frameParam_t voiceAmplitude; // amplitude of voice (phonation) source between 0 and 1.
|
||||
speechPlayer_frameParam_t aspirationAmplitude; // amplitude of aspiration (voiceless h, whisper) source between 0 and 1.
|
||||
speechPlayer_frameParam_t cf1, cf2, cf3, cf4, cf5, cf6, cfN0, cfNP; // frequencies of standard cascaide formants, nasal (anti) 0 and nasal pole in hz
|
||||
speechPlayer_frameParam_t cb1, cb2, cb3, cb4, cb5, cb6, cbN0, cbNP; // bandwidths of standard cascaide formants, nasal (anti) 0 and nasal pole in hz
|
||||
speechPlayer_frameParam_t caNP; // amplitude from 0 to 1 of cascade nasal pole formant
|
||||
// fricatives and parallel
|
||||
speechPlayer_frameParam_t fricationAmplitude; // amplitude of frication noise from 0 to 1.
|
||||
speechPlayer_frameParam_t pf1, pf2, pf3, pf4, pf5, pf6; // parallel formants in hz
|
||||
speechPlayer_frameParam_t pb1, pb2, pb3, pb4, pb5, pb6; // parallel formant bandwidths in hz
|
||||
speechPlayer_frameParam_t pa1, pa2, pa3, pa4, pa5, pa6; // amplitude of parallel formants between 0 and 1
|
||||
speechPlayer_frameParam_t parallelBypass; // amount of signal which should bypass parallel resonators from 0 to 1
|
||||
speechPlayer_frameParam_t preFormantGain; // amplitude from 0 to 1 of all vocal tract sound (voicing, frication) before entering formant resonators. Useful for stopping/starting speech
|
||||
speechPlayer_frameParam_t outputGain; // amplitude from 0 to 1 of final output (master volume)
|
||||
speechPlayer_frameParam_t endVoicePitch; // pitch of voice at the end of the frame length
|
||||
} speechPlayer_frame_t;
|
||||
|
||||
const int speechPlayer_frame_numParams=sizeof(speechPlayer_frame_t)/sizeof(speechPlayer_frameParam_t);
|
||||
|
||||
class FrameManager {
|
||||
public:
|
||||
static FrameManager* create(); //factory function
|
||||
virtual void queueFrame(speechPlayer_frame_t* frame, unsigned int minNumSamples, unsigned int numFadeSamples, int userIndex, bool purgeQueue)=0;
|
||||
virtual const speechPlayer_frame_t* const getCurrentFrame()=0;
|
||||
virtual const int getLastIndex()=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYER_SAMPLE_H
|
||||
#define SPEECHPLAYER_SAMPLE_H
|
||||
|
||||
typedef short sampleVal;
|
||||
|
||||
typedef struct {
|
||||
sampleVal value;
|
||||
} sample;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#include "frame.h"
|
||||
#include "speechWaveGenerator.h"
|
||||
#include "speechPlayer.h"
|
||||
|
||||
typedef struct {
|
||||
int sampleRate;
|
||||
FrameManager* frameManager;
|
||||
SpeechWaveGenerator* waveGenerator;
|
||||
} speechPlayer_handleInfo_t;
|
||||
|
||||
speechPlayer_handle_t speechPlayer_initialize(int sampleRate) {
|
||||
speechPlayer_handleInfo_t* playerHandleInfo=new speechPlayer_handleInfo_t;
|
||||
playerHandleInfo->sampleRate=sampleRate;
|
||||
playerHandleInfo->frameManager=FrameManager::create();
|
||||
playerHandleInfo->waveGenerator=SpeechWaveGenerator::create(sampleRate);
|
||||
playerHandleInfo->waveGenerator->setFrameManager(playerHandleInfo->frameManager);
|
||||
return (speechPlayer_handle_t)playerHandleInfo;
|
||||
}
|
||||
|
||||
void speechPlayer_queueFrame(speechPlayer_handle_t playerHandle, speechPlayer_frame_t* framePtr, unsigned int minFrameDuration, unsigned int fadeDuration, int userIndex, bool purgeQueue) {
|
||||
speechPlayer_handleInfo_t* playerHandleInfo=(speechPlayer_handleInfo_t*)playerHandle;
|
||||
if (fadeDuration < 1) fadeDuration = 1;
|
||||
playerHandleInfo->frameManager->queueFrame(framePtr,minFrameDuration,fadeDuration,userIndex,purgeQueue);
|
||||
}
|
||||
|
||||
int speechPlayer_synthesize(speechPlayer_handle_t playerHandle, unsigned int sampleCount, sample* sampleBuf) {
|
||||
return ((speechPlayer_handleInfo_t*)playerHandle)->waveGenerator->generate(sampleCount,sampleBuf);
|
||||
}
|
||||
|
||||
int speechPlayer_getLastIndex(speechPlayer_handle_t playerHandle) {
|
||||
speechPlayer_handleInfo_t* playerHandleInfo=(speechPlayer_handleInfo_t*)playerHandle;
|
||||
return playerHandleInfo->frameManager->getLastIndex();
|
||||
}
|
||||
|
||||
void speechPlayer_terminate(speechPlayer_handle_t playerHandle) {
|
||||
speechPlayer_handleInfo_t* playerHandleInfo=(speechPlayer_handleInfo_t*)playerHandle;
|
||||
delete playerHandleInfo->waveGenerator;
|
||||
delete playerHandleInfo->frameManager;
|
||||
delete playerHandleInfo;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYER_H
|
||||
#define SPEECHPLAYER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "frame.h"
|
||||
#include "sample.h"
|
||||
|
||||
typedef void* speechPlayer_handle_t;
|
||||
|
||||
speechPlayer_handle_t speechPlayer_initialize(int sampleRate);
|
||||
void speechPlayer_queueFrame(speechPlayer_handle_t playerHandle, speechPlayer_frame_t* framePtr, unsigned int minFrameDuration, unsigned int fadeDuration, int userIndex, bool purgeQueue);
|
||||
int speechPlayer_synthesize(speechPlayer_handle_t playerHandle, unsigned int sampleCount, sample* sampleBuf);
|
||||
int speechPlayer_getLastIndex(speechPlayer_handle_t playerHandle);
|
||||
void speechPlayer_terminate(speechPlayer_handle_t playerHandle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on klsyn-88, found at http://linguistics.berkeley.edu/phonlab/resources/
|
||||
*/
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include "utils.h"
|
||||
#include "speechWaveGenerator.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const double PITWO=M_PI*2;
|
||||
|
||||
class NoiseGenerator {
|
||||
private:
|
||||
double lastValue;
|
||||
|
||||
public:
|
||||
NoiseGenerator(): lastValue(0.0) {};
|
||||
|
||||
double getNext() {
|
||||
lastValue=((double)rand()/RAND_MAX)+0.75*lastValue;
|
||||
return lastValue;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FrequencyGenerator {
|
||||
private:
|
||||
int sampleRate;
|
||||
double lastCyclePos;
|
||||
|
||||
public:
|
||||
FrequencyGenerator(int sr): sampleRate(sr), lastCyclePos(0) {}
|
||||
|
||||
double getNext(double frequency) {
|
||||
double cyclePos=fmod((frequency/sampleRate)+lastCyclePos,1);
|
||||
lastCyclePos=cyclePos;
|
||||
return cyclePos;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class VoiceGenerator {
|
||||
private:
|
||||
FrequencyGenerator pitchGen;
|
||||
FrequencyGenerator vibratoGen;
|
||||
NoiseGenerator aspirationGen;
|
||||
|
||||
public:
|
||||
bool glottisOpen;
|
||||
VoiceGenerator(int sr): pitchGen(sr), vibratoGen(sr), aspirationGen(), glottisOpen(false) {};
|
||||
|
||||
double getNext(const speechPlayer_frame_t* frame) {
|
||||
double vibrato=(sin(vibratoGen.getNext(frame->vibratoSpeed)*PITWO)*0.06*frame->vibratoPitchOffset)+1;
|
||||
double voice=pitchGen.getNext(frame->voicePitch*vibrato);
|
||||
double aspiration=aspirationGen.getNext()*0.2;
|
||||
double turbulence=aspiration*frame->voiceTurbulenceAmplitude;
|
||||
glottisOpen=voice>=frame->glottalOpenQuotient;
|
||||
if(!glottisOpen) {
|
||||
turbulence*=0.01;
|
||||
}
|
||||
voice=(voice*2)-1;
|
||||
voice+=turbulence;
|
||||
voice*=frame->voiceAmplitude;
|
||||
aspiration*=frame->aspirationAmplitude;
|
||||
return aspiration+voice;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Resonator {
|
||||
private:
|
||||
//raw parameters
|
||||
int sampleRate;
|
||||
double frequency;
|
||||
double bandwidth;
|
||||
bool anti;
|
||||
//calculated parameters
|
||||
bool setOnce;
|
||||
double a, b, c;
|
||||
//Memory
|
||||
double p1, p2;
|
||||
|
||||
public:
|
||||
Resonator(int sampleRate, bool anti=false) {
|
||||
this->sampleRate=sampleRate;
|
||||
this->anti=anti;
|
||||
this->setOnce=false;
|
||||
this->p1=0;
|
||||
this->p2=0;
|
||||
}
|
||||
|
||||
void setParams(double frequency, double bandwidth) {
|
||||
if(!setOnce||(frequency!=this->frequency)||(bandwidth!=this->bandwidth)) {
|
||||
this->frequency=frequency;
|
||||
this->bandwidth=bandwidth;
|
||||
double r=exp(-M_PI/sampleRate*bandwidth);
|
||||
c=-(r*r);
|
||||
b=r*cos(PITWO/sampleRate*-frequency)*2.0;
|
||||
a=1.0-b-c;
|
||||
if(anti&&frequency!=0) {
|
||||
a=1.0/a;
|
||||
c*=-a;
|
||||
b*=-a;
|
||||
}
|
||||
}
|
||||
this->setOnce=true;
|
||||
}
|
||||
|
||||
double resonate(double in, double frequency, double bandwidth) {
|
||||
setParams(frequency,bandwidth);
|
||||
double out=a*in+b*p1+c*p2;
|
||||
p2=p1;
|
||||
p1=anti?in:out;
|
||||
return out;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class CascadeFormantGenerator {
|
||||
private:
|
||||
int sampleRate;
|
||||
Resonator r1, r2, r3, r4, r5, r6, rN0, rNP;
|
||||
|
||||
public:
|
||||
CascadeFormantGenerator(int sr): sampleRate(sr), r1(sr), r2(sr), r3(sr), r4(sr), r5(sr), r6(sr), rN0(sr,true), rNP(sr) {};
|
||||
|
||||
double getNext(const speechPlayer_frame_t* frame, bool glottisOpen, double input) {
|
||||
input/=2.0;
|
||||
double n0Output=rN0.resonate(input,frame->cfN0,frame->cbN0);
|
||||
double output=calculateValueAtFadePosition(input,rNP.resonate(n0Output,frame->cfNP,frame->cbNP),frame->caNP);
|
||||
output=r6.resonate(output,frame->cf6,frame->cb6);
|
||||
output=r5.resonate(output,frame->cf5,frame->cb5);
|
||||
output=r4.resonate(output,frame->cf4,frame->cb4);
|
||||
output=r3.resonate(output,frame->cf3,frame->cb3);
|
||||
output=r2.resonate(output,frame->cf2,frame->cb2);
|
||||
output=r1.resonate(output,frame->cf1,frame->cb1);
|
||||
return output;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ParallelFormantGenerator {
|
||||
private:
|
||||
int sampleRate;
|
||||
Resonator r1, r2, r3, r4, r5, r6;
|
||||
|
||||
public:
|
||||
ParallelFormantGenerator(int sr): sampleRate(sr), r1(sr), r2(sr), r3(sr), r4(sr), r5(sr), r6(sr) {};
|
||||
|
||||
double getNext(const speechPlayer_frame_t* frame, double input) {
|
||||
input/=2.0;
|
||||
double output=0;
|
||||
output+=(r1.resonate(input,frame->pf1,frame->pb1)-input)*frame->pa1;
|
||||
output+=(r2.resonate(input,frame->pf2,frame->pb2)-input)*frame->pa2;
|
||||
output+=(r3.resonate(input,frame->pf3,frame->pb3)-input)*frame->pa3;
|
||||
output+=(r4.resonate(input,frame->pf4,frame->pb4)-input)*frame->pa4;
|
||||
output+=(r5.resonate(input,frame->pf5,frame->pb5)-input)*frame->pa5;
|
||||
output+=(r6.resonate(input,frame->pf6,frame->pb6)-input)*frame->pa6;
|
||||
return calculateValueAtFadePosition(output,input,frame->parallelBypass);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SpeechWaveGeneratorImpl: public SpeechWaveGenerator {
|
||||
private:
|
||||
int sampleRate;
|
||||
VoiceGenerator voiceGenerator;
|
||||
NoiseGenerator fricGenerator;
|
||||
CascadeFormantGenerator cascade;
|
||||
ParallelFormantGenerator parallel;
|
||||
FrameManager* frameManager;
|
||||
|
||||
public:
|
||||
SpeechWaveGeneratorImpl(int sr): sampleRate(sr), voiceGenerator(sr), fricGenerator(), cascade(sr), parallel(sr), frameManager(NULL) {
|
||||
}
|
||||
|
||||
unsigned int generate(const unsigned int sampleCount, sample* sampleBuf) {
|
||||
if(!frameManager) return 0;
|
||||
double val=0;
|
||||
for(unsigned int i=0;i<sampleCount;++i) {
|
||||
const speechPlayer_frame_t* frame=frameManager->getCurrentFrame();
|
||||
if(frame) {
|
||||
double voice=voiceGenerator.getNext(frame);
|
||||
double cascadeOut=cascade.getNext(frame,voiceGenerator.glottisOpen,voice*frame->preFormantGain);
|
||||
double fric=fricGenerator.getNext()*0.3*frame->fricationAmplitude;
|
||||
double parallelOut=parallel.getNext(frame,fric*frame->preFormantGain);
|
||||
double out=(cascadeOut+parallelOut)*frame->outputGain;
|
||||
sampleBuf[i].value=(int)MAX(MIN(out*4000,32000),-32000);
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
void setFrameManager(FrameManager* frameManager) {
|
||||
this->frameManager=frameManager;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SpeechWaveGenerator* SpeechWaveGenerator::create(int sampleRate) {return new SpeechWaveGeneratorImpl(sampleRate); }
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYERSPEECHWAVEGENERATOR_H
|
||||
#define SPEECHPLAYERSPEECHWAVEGENERATOR_H
|
||||
|
||||
#include "frame.h"
|
||||
#include "waveGenerator.h"
|
||||
|
||||
class SpeechWaveGenerator: public WaveGenerator {
|
||||
public:
|
||||
static SpeechWaveGenerator* create(int sampleRate);
|
||||
virtual void setFrameManager(FrameManager* frameManager)=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYER_UTILS_H
|
||||
#define SPEECHPLAYER_UTILS_H
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
static inline int MAX(int a, int b) { return((a) > (b) ? a : b); }
|
||||
static inline int MIN(int a, int b) { return((a) < (b) ? a : b); }
|
||||
|
||||
static inline int ISNAN (double x) {
|
||||
if (x != x)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline double calculateValueAtFadePosition(double oldVal, double newVal, double curFadeRatio) {
|
||||
if(ISNAN(newVal)) return oldVal;
|
||||
return oldVal+((newVal-oldVal)*curFadeRatio);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is a part of the NV Speech Player project.
|
||||
URL: https://bitbucket.org/nvaccess/speechplayer
|
||||
Copyright 2014 NV Access Limited.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2.0, as published by
|
||||
the Free Software Foundation.
|
||||
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.
|
||||
This license can be found at:
|
||||
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#ifndef SPEECHPLAYERWAVEGENERATOR_H
|
||||
#define SPEECHPLAYERWAVEGENERATOR_H
|
||||
|
||||
#include <list>
|
||||
#include "sample.h"
|
||||
#include "speechPlayer.h"
|
||||
|
||||
class WaveGenerator {
|
||||
public:
|
||||
virtual unsigned int generate(const unsigned int bufSize, sample* buffer)=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user