/*************************************************************************** * Copyright (C) 2005 to 2007 by Jonathan Duddington * * email: jonsd@users.sourceforge.net * * Copyright (C) 2013-2015 by Reece H. Dunn * * * * 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 3 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, write see: * * . * ***************************************************************************/ #include "wx/wx.h" #include "speak_lib.h" #include "speech.h" #include "phoneme.h" #include "synthesize.h" #include "voice.h" #include "spect.h" #include "wx/txtstrm.h" #include "wx/datstrm.h" extern "C" int PeaksToHarmspect(wavegen_peaks_t *peaks, int pitch, int *htab, int control); extern unsigned char pk_shape1[]; extern int pk_select; extern char voice_name[]; static int frame_width; int pk_select; #define DRAWPEAKWIDTH 2000 #define PEAKSHAPEW 256 #include static int default_freq[N_PEAKS] = {200,500,1200,3000,3500,4000,6900,7800,9000}; static int default_width[N_PEAKS] = {750,500,550,550,600,700,700,700,700}; static int default_klt_bw[N_PEAKS] = {89,90,140,260,260,260,500,500,500}; float polint(float xa[],float ya[],int n,float x) {//============================================== // General polinomial interpolation routine, xa[1...n] ya[1...n] int i,m,ns=1; float den,dif,dift,ho,hp,w; float y; // result float c[9],d[9]; dif=fabs(x-xa[1]); for(i=1;i<=n;i++){ if((dift=fabs(x-xa[i])) < dif) { ns=i; dif=dift; } c[i]=ya[i]; d[i]=ya[i]; } y=ya[ns--]; for(m=1;mspect,sizeof(USHORT)*nx); } } SpectFrame::~SpectFrame() {//======================= if(spect != NULL) delete spect; } int SpectFrame::Load(wxInputStream& stream, int file_format_type) {//============================================================== int ix; int x; unsigned short *spect_data; wxDataInputStream s(stream); time = s.ReadDouble(); pitch = s.ReadDouble(); length = s.ReadDouble(); dx = s.ReadDouble(); nx = s.Read16(); markers = s.Read16(); amp_adjust = s.Read16(); if(file_format_type == 2) { ix = s.Read16(); // spare ix = s.Read16(); // spare } for(ix=0; ix 0) keyframe = 1; peaks[ix].pkwidth = s.Read16(); peaks[ix].pkright = s.Read16(); if(file_format_type == 2) { peaks[ix].klt_bw = s.Read16(); peaks[ix].klt_ap = s.Read16(); peaks[ix].klt_bp = s.Read16(); } } if(file_format_type > 0) { for(ix=0; ix max_y) max_y = x; } spect = spect_data; return(0); } // End of SpectFrame::Load double SpectFrame::GetRms(int seq_amplitude) {//========================================= int h; float total=0; int maxh; int height; int htab[400]; wavegen_peaks_t wpeaks[9]; for(h=0; h<9; h++) { height = (peaks[h].pkheight * seq_amplitude * amp_adjust)/10000; wpeaks[h].height = height << 8; wpeaks[h].freq = peaks[h].pkfreq << 16; wpeaks[h].left = peaks[h].pkwidth << 16; wpeaks[h].right = peaks[h].pkright << 16; } maxh = PeaksToHarmspect(wpeaks,90<<16,htab,0); for(h=1; h> 10); } rms = sqrt(total) / 7.25; return(rms); } SpectSeq::SpectSeq(int n) {//====================== numframes = n; if(n > 0) frames = new SpectFrame* [n]; else frames = NULL; pk_select = 1; grid = 1; duration = 0; pitch1 = 0; pitch2 = 0; bass_reduction = 0; max_x = 3000; max_y = 1; file_format = 0; } SpectSeq::~SpectSeq() {//================== int ix; if(frames != NULL) { for(ix=0; ix= numframes-1) return(0); // include the adjustment for this frame ? if(plus) adjust = frames[frame]->length_adjust; for(ix=frame+1; ixkeyframe) break; // reached next keyframe adjust += frames[ix]->length_adjust; } if(original != NULL) *original = int((frames[ix]->time - frames[frame]->time) * 1000.0 + 0.5); return ((frames[ix]->time - frames[frame]->time) * 1000.0 + adjust); } int SpectSeq::Load(wxInputStream & stream) {//======================================= int n; int ix; unsigned int id1, id2; int set_max_y=0; float time_offset; wxDataInputStream s(stream); id1 = s.Read32(); id2 = s.Read32(); if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEQ)) { file_format = 0; // eSpeak formants } else if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSEK)) { file_format = 1; // formants for Klatt synthesizer } else if((id1 == FILEID1_SPECTSEQ) && (id2 == FILEID2_SPECTSQ2)) { file_format = 2; // formants for Klatt synthesizer } else { fprintf(stderr, "Unsupported spectral file format.\n"); return(1); } name = s.ReadString(); n = s.Read16(); amplitude = s.Read16(); max_y = s.Read16(); s.Read16(); if(n==0) return(0); if(frames != NULL) delete frames; frames = new SpectFrame* [n]; numframes = 0; max_x = 3000; if(max_y == 0) { set_max_y = 1; max_y = 1; } for(ix = 0; ix < n; ix++) { SpectFrame *frame = new SpectFrame; if(frame->Load(stream, file_format) != 0) { delete frame; break; } frames[numframes++] = frame; if(set_max_y && (frame->max_y > max_y)) max_y = frame->max_y; if(frame->nx * frame->dx > max_x) max_x = int(frame->nx * frame->dx); } max_x = 9000; // disable auto-xscaling frame_width = int((FRAME_WIDTH*max_x)/MAX_DISPLAY_FREQ); if(frame_width > FRAME_WIDTH) frame_width = FRAME_WIDTH; // start times from zero time_offset = frames[0]->time; for(ix=0; ixtime -= time_offset; pitch1 = pitchenv.pitch1; pitch2 = pitchenv.pitch2; duration = int(frames[numframes-1]->time * 1000); if(max_y < 400) max_y = 200; else max_y = 29000; // disable auto height scaling for(ix=0; ixkeyframe) frames[ix]->length_adjust = frames[ix]->length - GetFrameLength(ix,0,NULL); } return(0); } // end of SpectSeq::Load