mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 02:42:50 +00:00
khotkeys: remove barely implemented voice trigger feature
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
ebe50d1a6d
commit
1fa840757f
16 changed files with 0 additions and 1618 deletions
|
@ -103,8 +103,6 @@ void KHotKeysModule::reread_configuration()
|
|||
kDebug() << _settings.areGesturesDisabled();
|
||||
KHotKeys::gesture_handler->enable( !_settings.areGesturesDisabled() );
|
||||
KHotKeys::gesture_handler->set_exclude( _settings.gesturesExclude() );
|
||||
// FIXME: SOUND
|
||||
// KHotKeys::voice_handler->set_shortcut( _settings.voice_shortcut );
|
||||
actions_root = _settings.actions();
|
||||
KHotKeys::khotkeys_set_active( true );
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ set(khotkeysprivate_SRCS
|
|||
triggers/trigger.cpp
|
||||
triggers/trigger_list.cpp
|
||||
triggers/triggers.cpp
|
||||
# triggers/voice_trigger.cpp
|
||||
triggers/window_trigger.cpp
|
||||
|
||||
# WINDOWS_HELPER
|
||||
|
@ -62,11 +61,6 @@ set(khotkeysprivate_SRCS
|
|||
settings_writer.cpp
|
||||
shortcuts_handler.cpp
|
||||
windows_handler.cpp
|
||||
# search for FIXME: SOUND
|
||||
# sound.cpp
|
||||
# soundrecorder.cpp
|
||||
# voices.cpp
|
||||
# voicesignature.cpp
|
||||
)
|
||||
|
||||
add_library(khotkeysprivate SHARED ${khotkeysprivate_SRCS})
|
||||
|
|
|
@ -19,12 +19,8 @@
|
|||
#include "windows_handler.h"
|
||||
#include "triggers/triggers.h"
|
||||
#include "triggers/gestures.h"
|
||||
#include "voices.h"
|
||||
#include "shortcuts_handler.h"
|
||||
|
||||
// FIXME: SOUND
|
||||
// #include "soundrecorder.h"
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
|
@ -49,8 +45,6 @@ void init_global_data( bool active_P, QObject* owner_P )
|
|||
{
|
||||
gesture_handler = new Gesture( active_P, owner_P );
|
||||
}
|
||||
// FIXME: SOUND
|
||||
// static_cast< void >( new Voice( active_P, owner_P ));
|
||||
khotkeys_set_active( false );
|
||||
}
|
||||
|
||||
|
|
|
@ -169,9 +169,6 @@ void Settings::reinitialize()
|
|||
|
||||
daemon_disabled = false;
|
||||
|
||||
// Currently unused
|
||||
voice_shortcut = KShortcut();
|
||||
|
||||
already_imported = QStringList();
|
||||
}
|
||||
|
||||
|
@ -211,12 +208,6 @@ void Settings::setGestureTimeOut(int timeout)
|
|||
}
|
||||
|
||||
|
||||
void Settings::setVoiceShortcut( const KShortcut &shortcut )
|
||||
{
|
||||
voice_shortcut = shortcut;
|
||||
}
|
||||
|
||||
|
||||
ActionDataGroup *Settings::takeActions()
|
||||
{
|
||||
ActionDataGroup *res = m_actions;
|
||||
|
@ -225,12 +216,6 @@ ActionDataGroup *Settings::takeActions()
|
|||
}
|
||||
|
||||
|
||||
KShortcut Settings::voiceShortcut() const
|
||||
{
|
||||
return voice_shortcut;
|
||||
}
|
||||
|
||||
|
||||
bool Settings::import(KConfig& config, ImportType ask, ActionState state)
|
||||
{
|
||||
return importFrom(m_actions, config, ask, state);
|
||||
|
@ -459,10 +444,6 @@ bool Settings::reread_settings(bool include_disabled)
|
|||
delete gestures_exclude;
|
||||
gestures_exclude = new Windowdef_list( gesturesExcludeConfig );
|
||||
|
||||
// ### Voice
|
||||
KConfigGroup voiceConfig( &config, "Voice" );
|
||||
voice_shortcut=KShortcut( voiceConfig.readEntry("Shortcut" , "") );
|
||||
|
||||
bool rc = read_settings(m_actions, config, include_disabled, Retain);
|
||||
// Ensure the system groups exist
|
||||
validate();
|
||||
|
|
|
@ -166,15 +166,6 @@ public:
|
|||
void setGesturesExclude( Windowdef_list *gestures );
|
||||
Windowdef_list *gesturesExclude();
|
||||
const Windowdef_list *gesturesExclude() const;
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Voice Commands
|
||||
*/
|
||||
//@{
|
||||
void setVoiceShortcut( const KShortcut &shortcut );
|
||||
KShortcut voiceShortcut() const;
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Check if the given config file is a valid khotkeys file
|
||||
|
@ -242,11 +233,6 @@ private:
|
|||
*/
|
||||
bool daemon_disabled;
|
||||
|
||||
/**
|
||||
* The shortcut that triggers a voice command
|
||||
*/
|
||||
KShortcut voice_shortcut;
|
||||
|
||||
/**
|
||||
* List of id's for all imported files.
|
||||
*/
|
||||
|
|
|
@ -267,8 +267,6 @@ void SettingsWriter::writeTo(KConfigBase &config)
|
|||
}
|
||||
else
|
||||
config.deleteGroup( "GesturesExclude" );
|
||||
KConfigGroup voiceConfig( &config, "Voice" );
|
||||
voiceConfig.writeEntry("Shortcut" , _settings->voice_shortcut.toString() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,343 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "sound.h"
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDataStream>
|
||||
#include <kdebug.h>
|
||||
|
||||
|
||||
|
||||
|
||||
Sound::Sound()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Sound::~Sound()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#define READ_FROM_STREAM(FORMAT,NAME) FORMAT NAME; stream >> NAME;
|
||||
#define MAGIC(CH) { \
|
||||
stream >> magic; \
|
||||
if( magic != ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ) \
|
||||
{ \
|
||||
kWarning() << "bad format " << magic << " != " << CH "\n";\
|
||||
return;\
|
||||
} }
|
||||
|
||||
#define ABS(X) ( (X>0) ? X : -X )
|
||||
|
||||
void Sound::load(const QString& filename)
|
||||
{
|
||||
kDebug() << filename;
|
||||
data=QVector<Q_INT32>();
|
||||
QFile file(filename);
|
||||
if(!file.open(IO_ReadOnly))
|
||||
{
|
||||
kWarning() <<"unable to open file" ;
|
||||
return;
|
||||
}
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder( QDataStream::LittleEndian );
|
||||
Q_INT32 magic;
|
||||
|
||||
MAGIC("RIFF");
|
||||
READ_FROM_STREAM(quint32,ChunkSize);
|
||||
MAGIC("WAVE");
|
||||
MAGIC("fmt ");
|
||||
READ_FROM_STREAM(quint32,ChunkSize2);
|
||||
READ_FROM_STREAM(Q_INT16,AudioFormat);
|
||||
READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
|
||||
READ_FROM_STREAM(quint32,SampleRate);
|
||||
_fs=SampleRate;
|
||||
READ_FROM_STREAM(quint32,ByteRate);
|
||||
READ_FROM_STREAM(Q_UINT16,BlockAlign);
|
||||
READ_FROM_STREAM(Q_UINT16,BitsPerSample);
|
||||
MAGIC("data");
|
||||
READ_FROM_STREAM(QByteArray,SoundData);
|
||||
NumberOfChannels=1; //Wav i play are broken
|
||||
|
||||
file.close();
|
||||
|
||||
uint BytePS=BitsPerSample/8;
|
||||
uint NumberOfSamples = (SoundData.size())/(NumberOfChannels*BytePS);
|
||||
|
||||
|
||||
data.resize(NumberOfSamples);
|
||||
|
||||
// kDebug() << NumberOfSamples << " samples";
|
||||
|
||||
max=0;
|
||||
for(unsigned long int f=0;f<NumberOfSamples;f++)
|
||||
{
|
||||
Q_INT32 nb=0;
|
||||
for(uint k=0;k<BytePS;k++)
|
||||
{
|
||||
nb |= (SoundData[(unsigned int)(f*BytePS+k)]&0x000000FF) << (k*8);
|
||||
}
|
||||
if(nb & (1 << (BytePS*8 -1)) )
|
||||
nb = nb-(1<<BytePS*8);
|
||||
data[f]=nb;
|
||||
if(ABS(nb)>max)
|
||||
{
|
||||
max=ABS(nb);
|
||||
}
|
||||
}
|
||||
|
||||
/* static int q=0;
|
||||
QString name="test" + QString::number(q++) + ".wav";
|
||||
save(name);*/
|
||||
|
||||
}
|
||||
|
||||
#define SMAGIC(CH) { stream << ( Q_INT32) ( (CH)[0] | (CH)[1]<<8 | (CH)[2]<< 16 | (CH)[3] << 24 ) ; }
|
||||
|
||||
void Sound::save(const QString& filename) const
|
||||
{
|
||||
kDebug() << filename << " - " << data.size() << endl;
|
||||
QFile file(filename);
|
||||
if(!file.open(IO_WriteOnly))
|
||||
{
|
||||
kWarning() <<"unable to open file" ;
|
||||
return;
|
||||
}
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder( QDataStream::LittleEndian );
|
||||
|
||||
|
||||
QByteArray SoundData(data.size()*2, '\0');
|
||||
|
||||
for(long int f=0;f<data.size();f++)
|
||||
{
|
||||
Q_UINT16 val= (signed short int) ( (data.at(f) * ((double)(1<<13)/(signed)max) ) );
|
||||
SoundData[ (uint)(2*f) ]= val & 0x00FF;
|
||||
SoundData[(uint)(2*f+1)]= (val & 0xFF00) >> 8;
|
||||
|
||||
// kDebug() << data.at(f) << " / " << max << " = " << val << " | " << SoundData[ 2*f ] << " "<< SoundData[ 2*f+1 ] << endl;
|
||||
}
|
||||
|
||||
Q_UINT16 NumberOfChannels=2;
|
||||
quint32 SampleRate=_fs;
|
||||
|
||||
SMAGIC("RIFF");
|
||||
//READ_FROM_STREAM(quint32,ChunkSize);
|
||||
stream << (quint32)(36+ SoundData.size());
|
||||
SMAGIC("WAVE");
|
||||
SMAGIC("fmt ");
|
||||
//READ_FROM_STREAM(quint32,ChunkSize2);
|
||||
stream << (quint32)(16);
|
||||
//READ_FROM_STREAM(Q_INT16,AudioFormat);
|
||||
stream << (Q_INT16)(1);
|
||||
//READ_FROM_STREAM(Q_UINT16,NumberOfChannels);
|
||||
stream << (Q_UINT16)(NumberOfChannels);
|
||||
//READ_FROM_STREAM(quint32,SampleRate);
|
||||
stream << (quint32)(SampleRate);
|
||||
//READ_FROM_STREAM(quint32,ByteRate);
|
||||
stream << (quint32)(NumberOfChannels*SampleRate*16/8);
|
||||
//READ_FROM_STREAM(Q_UINT16,BlockAlign);
|
||||
stream << (Q_UINT16)(16/8 *NumberOfChannels);
|
||||
//READ_FROM_STREAM(Q_UINT16,BitsPerSample);
|
||||
stream << (Q_UINT16)(16);
|
||||
SMAGIC("data");
|
||||
//READ_FROM_STREAM(QByteArray,SoundData);
|
||||
stream << SoundData;
|
||||
|
||||
file.close();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
void Sound::load(const QString& filename)
|
||||
{
|
||||
cout << "saout \n";
|
||||
data=QMemArray<long unsigned int>();
|
||||
static const int BUFFER_LEN = 4096;
|
||||
|
||||
//code from libtunepimp
|
||||
//(wav_trm.cpp)
|
||||
|
||||
FILE *source;
|
||||
unsigned char buffer[100], *copyBuffer;
|
||||
unsigned int bytes;
|
||||
unsigned long ulRIFF;
|
||||
unsigned long ulLength;
|
||||
unsigned long ulWAVE;
|
||||
unsigned long ulType;
|
||||
unsigned long ulCount;
|
||||
unsigned long ulLimit;
|
||||
bool haveWaveHeader = false;
|
||||
unsigned long waveSize = 0;
|
||||
WAVEFORMAT waveFormat;
|
||||
int toRead;
|
||||
mb_int64_t fileLen = 0;
|
||||
|
||||
source = fopen(filename.ascii(), "rb");
|
||||
if (source == NULL)
|
||||
{
|
||||
// errorString = string("File not found");
|
||||
// fclose(source);
|
||||
cout << "File not found \n";
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(source, 0, SEEK_END);
|
||||
fileLen = ftell(source);
|
||||
fseek(source, 0, SEEK_SET);
|
||||
|
||||
if (fread(buffer, 1, 12, source) != 12)
|
||||
{
|
||||
// errorString = string("File is too short");
|
||||
cout << "File is to short \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
|
||||
ulRIFF = (unsigned long)(((unsigned long *)buffer)[0]);
|
||||
ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
|
||||
ulWAVE = (unsigned long)(((unsigned long *)buffer)[2]);
|
||||
|
||||
if(ulRIFF != MAKEFOURCC('R', 'I', 'F', 'F') ||
|
||||
ulWAVE != MAKEFOURCC('W', 'A', 'V', 'E'))
|
||||
{
|
||||
// errorString = strdup("File is not in WAVE format");
|
||||
cout << "File is not WAVE \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
|
||||
// Run through the bytes looking for the tags
|
||||
ulCount = 0;
|
||||
ulLimit = ulLength - 4;
|
||||
while (ulCount < ulLimit && waveSize == 0)
|
||||
{
|
||||
if (fread(buffer, 1, 8, source) != 8)
|
||||
{
|
||||
// errorString = strdup("File is too short");
|
||||
cout << "File is to short \n";
|
||||
fclose(source);
|
||||
return;
|
||||
}
|
||||
|
||||
ulType = (unsigned long)(((unsigned long *)buffer)[0]);
|
||||
ulLength = (unsigned long)(((unsigned long *)buffer)[1]);
|
||||
switch (ulType)
|
||||
{
|
||||
// format
|
||||
case MAKEFOURCC('f', 'm', 't', ' '):
|
||||
if (ulLength < sizeof(WAVEFORMAT))
|
||||
{
|
||||
// errorString = strdup("File is too short");
|
||||
cout << "File is to short \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
|
||||
if (fread(&waveFormat, 1, ulLength, source) != ulLength)
|
||||
{
|
||||
// errorString = strdup("File is too short");
|
||||
cout << "File is to short \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
|
||||
if (waveFormat.wFormatTag != WAVE_FORMAT_PCM)
|
||||
{
|
||||
// errorString = strdup("Unsupported WAV format");
|
||||
cout << "Unsupported WAVE \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
haveWaveHeader = true;
|
||||
|
||||
ulCount += ulLength;
|
||||
break;
|
||||
|
||||
// data
|
||||
case MAKEFOURCC('d', 'a', 't', 'a'):
|
||||
waveSize = ulLength;
|
||||
break;
|
||||
|
||||
default:
|
||||
fseek(source, ulLength, SEEK_CUR);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!haveWaveHeader)
|
||||
{
|
||||
// errorString = strdup("Could not find WAV header");
|
||||
cout << "Header nbot found \n";
|
||||
fclose(source);
|
||||
return ;
|
||||
}
|
||||
|
||||
fileLen -= (mb_int64_t)ftell(source);
|
||||
fileLen /= waveFormat.nChannels;
|
||||
fileLen /= (waveFormat.nBlockAlign / waveFormat.nChannels);
|
||||
|
||||
fileLen /= waveFormat.nSamplesPerSec;
|
||||
|
||||
//on ne lit qu'un channel
|
||||
//waveSize=fileLen;
|
||||
data.resize(waveSize);
|
||||
unsigned long pos=0;
|
||||
|
||||
cout << "Weeee "<< waveSize <<"\n";
|
||||
|
||||
copyBuffer = (unsigned char*)malloc(BUFFER_LEN);
|
||||
if (copyBuffer == NULL)
|
||||
{
|
||||
// errorString = strdup("Cannot allocate buffer space.");
|
||||
return ;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
toRead = min(waveSize, (unsigned long)BUFFER_LEN);
|
||||
if (toRead <= 0)
|
||||
break;
|
||||
|
||||
bytes = fread(copyBuffer, 1, toRead, source);
|
||||
if (bytes <= 0)
|
||||
break;
|
||||
|
||||
for(uint f=0;f<bytes;f+=4)
|
||||
{
|
||||
data[pos]=(((unsigned long*)copyBuffer)[f/4]);
|
||||
pos++;
|
||||
}
|
||||
|
||||
waveSize -= toRead;
|
||||
}
|
||||
free(copyBuffer);
|
||||
fclose(source);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,58 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <kdemacros.h>
|
||||
|
||||
/**
|
||||
@author Olivier Goffart
|
||||
*/
|
||||
class KDE_EXPORT Sound{
|
||||
public:
|
||||
Sound();
|
||||
~Sound();
|
||||
|
||||
void load(const QString &filename);
|
||||
void save(const QString &filename) const;
|
||||
|
||||
unsigned int size() const
|
||||
{
|
||||
return data.size();
|
||||
}
|
||||
|
||||
inline float at(int pos) const
|
||||
{
|
||||
return (float)(data.at(pos))/max;
|
||||
}
|
||||
|
||||
inline uint fs() const
|
||||
{
|
||||
return _fs;
|
||||
}
|
||||
|
||||
QVector<Q_INT32> data;
|
||||
quint32 max;
|
||||
uint _fs;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,81 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "soundrecorder.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <klocale.h>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QLibrary>
|
||||
|
||||
#include "khotkeysglobal.h"
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
SoundRecorder::create_ptr SoundRecorder::create_fun = NULL;
|
||||
|
||||
bool SoundRecorder::init( QLibrary* lib )
|
||||
{
|
||||
#ifdef HAVE_ARTS
|
||||
if( create_fun == NULL && lib != NULL )
|
||||
create_fun = (create_ptr) lib->symbol( "khotkeys_soundrecorder_create" );
|
||||
#endif
|
||||
// kDebug() << "soundrecorder:" << create_fun << ":" << lib;
|
||||
return create_fun != NULL;
|
||||
}
|
||||
|
||||
SoundRecorder* SoundRecorder::create( QObject* parent )
|
||||
{
|
||||
#ifdef HAVE_ARTS
|
||||
if( create_fun != NULL )
|
||||
return create_fun( parent, name );
|
||||
#endif
|
||||
return new SoundRecorder( parent );
|
||||
}
|
||||
|
||||
SoundRecorder::SoundRecorder(QObject *parent) : QObject(parent) {}
|
||||
|
||||
SoundRecorder::~SoundRecorder()
|
||||
{
|
||||
}
|
||||
|
||||
void SoundRecorder::start()
|
||||
{
|
||||
}
|
||||
|
||||
void SoundRecorder::stop()
|
||||
{
|
||||
}
|
||||
|
||||
void SoundRecorder::abort()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Sound SoundRecorder::sound()
|
||||
{
|
||||
Sound s;
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_soundrecorder.cpp"
|
|
@ -1,62 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef RECORDER_H
|
||||
#define RECORDER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include "sound.h"
|
||||
#include <kdemacros.h>
|
||||
|
||||
#include <QLibrary>
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@author Olivier Goffart
|
||||
*/
|
||||
class KDE_EXPORT SoundRecorder : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static SoundRecorder* create( QObject* parent = 0 );
|
||||
virtual ~SoundRecorder();
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void abort();
|
||||
virtual Sound sound();
|
||||
|
||||
static bool init( QLibrary* );
|
||||
signals:
|
||||
void recorded(const Sound&);
|
||||
|
||||
protected:
|
||||
SoundRecorder(QObject *parent = 0);
|
||||
typedef SoundRecorder* (*create_ptr)( QObject*, const char* );
|
||||
private:
|
||||
static create_ptr create_fun;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include <kdemacros.h>
|
||||
#include "khotkeysglobal.h"
|
||||
#include "voicesignature.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "windows_handler.h"
|
||||
|
@ -351,50 +350,6 @@ class KDE_EXPORT GestureTrigger
|
|||
|
||||
StrokePoints _pointdata;
|
||||
};
|
||||
|
||||
|
||||
// FIXME: SOUND
|
||||
#if 0
|
||||
class KDE_EXPORT Voice_trigger
|
||||
: public QObject, public Trigger
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef Trigger base;
|
||||
public:
|
||||
Voice_trigger( ActionData* data_P, const QString& Voice_P, const VoiceSignature & signature1_P, const VoiceSignature & signature2_P );
|
||||
Voice_trigger( KConfigGroup& cfg_P, ActionData* data_P );
|
||||
virtual ~Voice_trigger();
|
||||
virtual void cfg_write( KConfigGroup& cfg_P ) const;
|
||||
virtual Trigger* copy( ActionData* data_P ) const;
|
||||
virtual const QString description() const;
|
||||
const QString& voicecode() const;
|
||||
virtual void activate( bool activate_P );
|
||||
VoiceSignature voicesignature( int ech ) const;
|
||||
|
||||
virtual TriggerType type() const { return SoundTrigger; }
|
||||
public slots:
|
||||
void handle_Voice( );
|
||||
private:
|
||||
QString _voicecode;
|
||||
VoiceSignature _voicesignature[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
// FIXME: SOUND
|
||||
#if 0
|
||||
// Voice_trigger
|
||||
inline
|
||||
const QString& Voice_trigger::voicecode() const
|
||||
{
|
||||
return _voicecode;
|
||||
}
|
||||
|
||||
inline
|
||||
VoiceSignature Voice_trigger::voicesignature(int ech) const
|
||||
{
|
||||
return _voicesignature[ech-1];
|
||||
}
|
||||
#endif
|
||||
} // namespace KHotKeys
|
||||
|
||||
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 1999-2001 Lubos Lunak <l.lunak@kde.org>
|
||||
Copyright (C) 2008 Michael Jansen <kde@michael-jansen.biz>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "triggers.h"
|
||||
#include "action_data.h"
|
||||
#include "voices.h"
|
||||
#include "windows.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KDebug>
|
||||
|
||||
namespace KHotKeys {
|
||||
|
||||
Voice_trigger::Voice_trigger( ActionData* data_P, const QString &Voicecode_P, const VoiceSignature& signature1_P, const VoiceSignature& signature2_P )
|
||||
: Trigger( data_P ), _voicecode( Voicecode_P )
|
||||
{
|
||||
_voicesignature[0]=signature1_P;
|
||||
_voicesignature[1]=signature2_P;
|
||||
}
|
||||
|
||||
Voice_trigger::Voice_trigger( KConfigGroup& cfg_P, ActionData* data_P )
|
||||
: Trigger( cfg_P, data_P )
|
||||
{
|
||||
_voicecode = cfg_P.readEntry( "Name" );
|
||||
_voicesignature[0].read( cfg_P , "Signature1" );
|
||||
_voicesignature[1].read( cfg_P , "Signature2" );
|
||||
}
|
||||
|
||||
Voice_trigger::~Voice_trigger()
|
||||
{
|
||||
voice_handler->unregister_handler( this );
|
||||
}
|
||||
|
||||
void Voice_trigger::cfg_write( KConfigGroup& cfg_P ) const
|
||||
{
|
||||
base::cfg_write( cfg_P );
|
||||
cfg_P.writeEntry( "Name", voicecode());
|
||||
cfg_P.writeEntry( "Type", "VOICE" ); // overwrites value set in base::cfg_write()
|
||||
_voicesignature[0].write( cfg_P , "Signature1" );
|
||||
_voicesignature[1].write( cfg_P , "Signature2" );
|
||||
}
|
||||
|
||||
Trigger* Voice_trigger::copy( ActionData* data_P ) const
|
||||
{
|
||||
kDebug() << "Voice_trigger::copy()";
|
||||
return new Voice_trigger( data_P ? data_P : data, voicecode(), voicesignature(1) , voicesignature(2) );
|
||||
}
|
||||
|
||||
const QString Voice_trigger::description() const
|
||||
{
|
||||
return i18n( "Voice trigger: " ) + voicecode();
|
||||
}
|
||||
|
||||
void Voice_trigger::handle_Voice( )
|
||||
{
|
||||
windows_handler->set_action_window( 0 ); // use active window
|
||||
data->execute();
|
||||
|
||||
}
|
||||
|
||||
void Voice_trigger::activate( bool activate_P )
|
||||
{
|
||||
if( activate_P && khotkeys_active())
|
||||
voice_handler->register_handler( this );
|
||||
else
|
||||
voice_handler->unregister_handler( this );
|
||||
}
|
||||
|
||||
} // namespace KHotKeys
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
/****************************************************************************
|
||||
|
||||
KHotKeys
|
||||
|
||||
Copyright (C) 2005 Olivier Goffart <ogoffart @ kde.org>
|
||||
|
||||
Distributed under the terms of the GNU General Public License version 2.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <kaction.h>
|
||||
|
||||
#include "voices.h"
|
||||
#include "voicesignature.h"
|
||||
#include "triggers.h"
|
||||
#include "soundrecorder.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#include <kapplication.h>
|
||||
#include <kdebug.h>
|
||||
#include <kxerrorhandler.h>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <fixx11h.h>
|
||||
|
||||
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
Voice* voice_handler;
|
||||
|
||||
Voice::Voice( bool enabled_P, QObject* parent_P )
|
||||
: QObject( parent_P) ,_enabled( enabled_P ), _recording( false ), _recorder(0)
|
||||
{
|
||||
assert( voice_handler == NULL );
|
||||
voice_handler = this;
|
||||
|
||||
_kga=0L;
|
||||
_timer=0L;
|
||||
|
||||
kDebug() ;
|
||||
|
||||
}
|
||||
|
||||
Voice::~Voice()
|
||||
{
|
||||
kDebug() ;
|
||||
enable( false );
|
||||
voice_handler = NULL;
|
||||
}
|
||||
|
||||
|
||||
void Voice::enable( bool enabled_P )
|
||||
{
|
||||
#ifndef HAVE_ARTS
|
||||
enabled_P = false; // never enabled when there's no support
|
||||
#endif
|
||||
if( _enabled == enabled_P )
|
||||
return;
|
||||
_enabled = enabled_P;
|
||||
_kga->setEnabled(enabled_P);
|
||||
}
|
||||
|
||||
void Voice::register_handler( Voice_trigger *trigger_P )
|
||||
{
|
||||
if( !_references.contains( trigger_P ))
|
||||
_references.append(trigger_P);
|
||||
}
|
||||
|
||||
void Voice::unregister_handler( Voice_trigger *trigger_P )
|
||||
{
|
||||
_references.remove(trigger_P);
|
||||
}
|
||||
|
||||
|
||||
void Voice::record_start()
|
||||
{
|
||||
kDebug() ;
|
||||
if(!_recorder)
|
||||
{
|
||||
_recorder= SoundRecorder::create(this);
|
||||
connect(_recorder, SIGNAL(recorded(Sound)), this, SLOT(slot_sound_recorded(Sound)));
|
||||
}
|
||||
|
||||
_recorder->start();
|
||||
_recording=true;
|
||||
}
|
||||
|
||||
void Voice::record_stop()
|
||||
{
|
||||
if(!_recording)
|
||||
return;
|
||||
|
||||
kDebug() ;
|
||||
delete _timer;
|
||||
_timer=0L;
|
||||
_recording=false;
|
||||
if(_recorder)
|
||||
_recorder->stop();
|
||||
}
|
||||
|
||||
|
||||
void Voice::slot_sound_recorded(const Sound &sound_P)
|
||||
{
|
||||
VoiceSignature signature(sound_P);
|
||||
|
||||
Voice_trigger *trig=0L;
|
||||
Voice_trigger *sec_trig=0L;
|
||||
double minimum=800000;
|
||||
double second_minimum=80000;
|
||||
int got_count=0;
|
||||
foreach(Voice_trigger *t, _references)
|
||||
{
|
||||
for(int ech=1; ech<=2 ; ech++)
|
||||
{
|
||||
double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
|
||||
if(minimum>=diff)
|
||||
{
|
||||
second_minimum=minimum;
|
||||
minimum=diff;
|
||||
sec_trig=trig;
|
||||
trig=t;
|
||||
}
|
||||
else if(second_minimum>=diff)
|
||||
{
|
||||
second_minimum=diff;
|
||||
sec_trig=t;
|
||||
}
|
||||
if( diff < REJECT_FACTOR_DIFF )
|
||||
got_count++;
|
||||
kDebug() << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff;
|
||||
}
|
||||
}
|
||||
// double ecart_relatif=(second_minimum-minimum)/minimum;
|
||||
|
||||
// kDebug() << ecart_relatif;
|
||||
|
||||
if(trig)
|
||||
kDebug() << "**** " << trig->voicecode() << " : " << minimum;
|
||||
|
||||
|
||||
// if(trig && ecart_relatif > REJECT_FACTOR_ECART_REL)
|
||||
// if(trig && got_count==1)
|
||||
bool selected=trig && (got_count==1 || ( minimum < 1.5*REJECT_FACTOR_DIFF && trig==sec_trig ) );
|
||||
|
||||
if(selected)
|
||||
{
|
||||
trig->handle_Voice();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*bool Voice::x11Event( XEvent* pEvent )
|
||||
{
|
||||
if( pEvent->type != XKeyPress && pEvent->type != XKeyRelease )
|
||||
return false;
|
||||
|
||||
KKeyNative keyNative( pEvent );
|
||||
|
||||
//kDebug() << keyNative.key().toString();
|
||||
|
||||
if(_shortcut.contains(keyNative))
|
||||
{
|
||||
if(pEvent->type == XKeyPress && !_recording )
|
||||
{
|
||||
record_start();
|
||||
return true;
|
||||
}
|
||||
if(pEvent->type == XKeyRelease && _recording )
|
||||
{
|
||||
record_stop();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void Voice::set_shortcut( const KShortcut &shortcut)
|
||||
{
|
||||
_shortcut = shortcut;
|
||||
if( !_enabled )
|
||||
return;
|
||||
if(!_kga)
|
||||
{
|
||||
_kga = new KAction(this);
|
||||
_kga->setObjectName("khotkeys_voice");
|
||||
connect(_kga,SIGNAL(triggered(bool)) , this , SLOT(slot_key_pressed()));
|
||||
}
|
||||
_kga->setGlobalShortcut(shortcut);
|
||||
}
|
||||
|
||||
void Voice::slot_key_pressed()
|
||||
{
|
||||
if( _recording )
|
||||
record_stop();
|
||||
else
|
||||
{
|
||||
record_start();
|
||||
if(!_timer)
|
||||
{
|
||||
_timer=new QTimer(this);
|
||||
connect(_timer, SIGNAL(timeout()) , this, SLOT(slot_timeout()));
|
||||
}
|
||||
_timer->setSingleShot(true);
|
||||
_timer->start(1000*20);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Voice::slot_timeout()
|
||||
{
|
||||
if(_recording && _recorder)
|
||||
{
|
||||
_recorder->abort();
|
||||
_recording=false;
|
||||
}
|
||||
_timer->deleteLater();
|
||||
_timer=0L;
|
||||
}
|
||||
|
||||
|
||||
QString Voice::isNewSoundFarEnough(const VoiceSignature& signature, const QString ¤tTrigger)
|
||||
{
|
||||
Voice_trigger *trig=0L;
|
||||
Voice_trigger *sec_trig=0L;
|
||||
double minimum=800000;
|
||||
double second_minimum=80000;
|
||||
int got_count=0;
|
||||
foreach (Voice_trigger *t , _references)
|
||||
{
|
||||
if(t->voicecode()==currentTrigger)
|
||||
continue;
|
||||
|
||||
for(int ech=1; ech<=2 ; ech++)
|
||||
{
|
||||
double diff=VoiceSignature::diff(signature, t->voicesignature(ech));
|
||||
if(minimum>=diff)
|
||||
{
|
||||
second_minimum=minimum;
|
||||
minimum=diff;
|
||||
sec_trig=trig;
|
||||
trig=t;
|
||||
}
|
||||
else if(second_minimum>=diff)
|
||||
{
|
||||
second_minimum=diff;
|
||||
sec_trig=t;
|
||||
}
|
||||
if( diff < REJECT_FACTOR_DIFF )
|
||||
got_count++;
|
||||
kDebug() << ( (diff < REJECT_FACTOR_DIFF) ? "+++" : "---" ) <<t->voicecode() << ech << " : " << diff;
|
||||
}
|
||||
}
|
||||
|
||||
if(trig)
|
||||
kDebug() << "**** " << trig->voicecode() << " : " << minimum;
|
||||
|
||||
bool selected=trig && ((got_count==1 && minimum < REJECT_FACTOR_DIFF*0.7 ) || ( minimum < REJECT_FACTOR_DIFF && trig==sec_trig ) );
|
||||
return selected ? trig->voicecode() : QString();
|
||||
}
|
||||
|
||||
bool Voice::doesVoiceCodeExists(const QString &vc)
|
||||
{
|
||||
foreach (Voice_trigger *t , _references)
|
||||
{
|
||||
if(t->voicecode()==vc)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace KHotKeys
|
||||
|
||||
#include "moc_voices.cpp"
|
|
@ -1,83 +0,0 @@
|
|||
/****************************************************************************
|
||||
|
||||
KHotKeys
|
||||
|
||||
Copyright (C) 2005 Olivier Goffart <ogoffart @ kde.org>
|
||||
|
||||
Distributed under the terms of the GNU General Public License version 2.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef VOICES_H_
|
||||
#define VOICES_H_
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <kshortcut.h>
|
||||
|
||||
class Sound;
|
||||
#include <QTimer>
|
||||
class KAction;
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
class Voice;
|
||||
class SoundRecorder;
|
||||
|
||||
class Voice_trigger;
|
||||
class VoiceSignature;
|
||||
|
||||
|
||||
class KDE_EXPORT Voice : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Voice( bool enabled_P, QObject* parent_P );
|
||||
virtual ~Voice();
|
||||
void enable( bool enable_P );
|
||||
|
||||
void register_handler( Voice_trigger* );
|
||||
void unregister_handler( Voice_trigger* );
|
||||
// bool x11Event( XEvent* e );
|
||||
|
||||
void set_shortcut( const KShortcut &k);
|
||||
|
||||
/**
|
||||
* return QString() is a new signature is far enough from others signature
|
||||
* otherwise, return the stringn which match.
|
||||
*/
|
||||
QString isNewSoundFarEnough(const VoiceSignature& s, const QString& currentTrigger);
|
||||
|
||||
bool doesVoiceCodeExists(const QString &s);
|
||||
|
||||
public slots:
|
||||
void record_start();
|
||||
void record_stop();
|
||||
|
||||
private slots:
|
||||
void slot_sound_recorded( const Sound & );
|
||||
void slot_key_pressed();
|
||||
void slot_timeout();
|
||||
|
||||
signals:
|
||||
void handle_voice( const QString &voice );
|
||||
private:
|
||||
|
||||
bool _enabled;
|
||||
bool _recording;
|
||||
|
||||
QList<Voice_trigger *> _references;
|
||||
SoundRecorder *_recorder;
|
||||
|
||||
KShortcut _shortcut;
|
||||
KAction *_kga;
|
||||
|
||||
QTimer *_timer;
|
||||
};
|
||||
|
||||
|
||||
KDE_EXPORT extern Voice* voice_handler;
|
||||
|
||||
} // namespace KHotKeys
|
||||
|
||||
#endif
|
|
@ -1,423 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#include "voicesignature.h"
|
||||
#include "sound.h"
|
||||
#include <kconfig.h>
|
||||
#include <kconfiggroup.h>
|
||||
|
||||
#include <math.h>
|
||||
#ifdef PI
|
||||
#undef PI
|
||||
#endif
|
||||
#define PI (2.0 * asin(1.0))
|
||||
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <QtCore/qdatetime.h>
|
||||
|
||||
#undef Complex
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
|
||||
inline static float ABS(float X)
|
||||
{
|
||||
return (X>0) ? X : -X ;
|
||||
}
|
||||
inline static int MAX(int X , int Y)
|
||||
{
|
||||
return (X>Y) ? X : Y ;
|
||||
}
|
||||
inline static int MIN(int X , int Y)
|
||||
{
|
||||
return (X<Y) ? X : Y ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Complex
|
||||
{
|
||||
public:
|
||||
Complex () {}
|
||||
Complex (double re): _re(re), _im(0.0) {}
|
||||
Complex (double re, double im): _re(re), _im(im) {}
|
||||
double Re () const { return _re; }
|
||||
double Im () const { return _im; }
|
||||
void operator += (const Complex& c)
|
||||
{
|
||||
_re += c._re;
|
||||
_im += c._im;
|
||||
}
|
||||
void operator -= (const Complex& c)
|
||||
{
|
||||
_re -= c._re;
|
||||
_im -= c._im;
|
||||
}
|
||||
void operator *= (const Complex& c)
|
||||
{
|
||||
double reT = c._re * _re - c._im * _im;
|
||||
_im = c._re * _im + c._im * _re;
|
||||
_re = reT;
|
||||
}
|
||||
Complex operator- ()
|
||||
{
|
||||
return Complex (-_re, -_im);
|
||||
}
|
||||
Complex operator- (const Complex& c) const
|
||||
{
|
||||
return Complex (_re - c._re, _im - c._im);
|
||||
}
|
||||
Complex operator+ (const Complex& c) const
|
||||
{
|
||||
return Complex (_re + c._re, _im + c._im);
|
||||
}
|
||||
Complex operator* (const Complex& c) const
|
||||
{
|
||||
return Complex (_re * c._re - _im * c._im , _im * c._re + _re * c._im);
|
||||
}
|
||||
double Mod () const { return sqrt (_re * _re + _im * _im); }
|
||||
|
||||
static Complex fromExp(double mod, double arg) { return Complex(mod*cos(arg) , mod*sin(arg)); }
|
||||
private:
|
||||
double _re;
|
||||
double _im;
|
||||
};
|
||||
|
||||
static inline double hamming(uint n, uint size)
|
||||
{
|
||||
return HAMMING ? 0.54-0.46*cos( 2*PI*n /(size-1) ) : 1;
|
||||
}
|
||||
|
||||
|
||||
static QVector<double> fft(const Sound& sound, unsigned int start, unsigned int stop)
|
||||
{
|
||||
if(start>=stop || sound.size()==0)
|
||||
return QVector<double>();
|
||||
|
||||
//We need a sample with a size of a power of two
|
||||
uint size=stop-start;
|
||||
unsigned short log2size=0;
|
||||
while( (1<<log2size) < size )
|
||||
log2size++;
|
||||
|
||||
int diff=(1<<log2size) - size;
|
||||
if(diff > size/4 || 1<<log2size > sound.size() )
|
||||
{
|
||||
log2size--;
|
||||
diff=(1<<log2size) - size;
|
||||
}
|
||||
size=1<<log2size;
|
||||
int start2=start-diff/2;
|
||||
int stop2=start2+ size;
|
||||
if(start2<0)
|
||||
{
|
||||
stop2-=start2;
|
||||
start2=0;
|
||||
}
|
||||
if(stop2>sound.size())
|
||||
{
|
||||
start2-= stop2 - sound.size();
|
||||
stop2=sound.size();
|
||||
if(start2<0)
|
||||
{
|
||||
stop2-=start2;
|
||||
start2=0;
|
||||
}
|
||||
}
|
||||
|
||||
//Generate an array to work in
|
||||
QVector<Complex> samples(size);
|
||||
|
||||
//Fill it with samples in the "reversed carry" order
|
||||
int rev_carry = 0;
|
||||
for (uint f = 0; f < size - 1; f++)
|
||||
{
|
||||
samples[f]=sound.at(start2+rev_carry)* hamming(rev_carry, size);
|
||||
// KDEBUG(rev_carry);
|
||||
int mask = size>>1; // N / 2
|
||||
// add 1 backwards
|
||||
while (rev_carry >= mask)
|
||||
{
|
||||
rev_carry -= mask; // turn off this bit
|
||||
mask >>= 1;
|
||||
}
|
||||
rev_carry += mask;
|
||||
}
|
||||
samples[size-1]=sound.at(start2+size-1)*hamming(size-1, size);
|
||||
|
||||
//FFT
|
||||
for(uint level=0; level < log2size; level++)
|
||||
{
|
||||
for( int k=0; k< (size>>1) ; k++)
|
||||
{
|
||||
uint indice1 = (k << (level+1) ) % (size-1); // (k*2*2^l)%(N-1)
|
||||
uint indice2 = indice1 + (1<<level); // (k*2*2^l)%(N-1) + 2^l
|
||||
|
||||
uint coefW = ( k << (level+1) ) / (size-1); // (k*2*2^l) div (N-1)
|
||||
double Wexpn=-2 * PI * coefW / (2 << level); // -2 pi n / 2^(l+1)
|
||||
Complex W=Complex::fromExp(1, Wexpn) ;
|
||||
|
||||
|
||||
//OPERATION BUTTERFLY
|
||||
Complex a=samples[indice1];
|
||||
Complex b=samples[indice2];
|
||||
samples[indice1]=a+W*b;
|
||||
samples[indice2]=a-W*b;
|
||||
|
||||
// kDebug() << "PAPILLON s_" << indice1 << " s_" << indice2 << " W_" << (2<<level) << "^" << coefW;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<double> result(size);
|
||||
for(uint f=0;f<size;f++)
|
||||
{
|
||||
result[f]=samples[f].Mod() / size;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QVector<double> VoiceSignature::fft(const Sound& sound, unsigned int start, unsigned int stop)
|
||||
{
|
||||
return KHotKeys::fft(sound, start, stop);
|
||||
/*QVector<double> result(8000);
|
||||
for(int f=0; f<8000;f++)
|
||||
{
|
||||
Complex c(0);
|
||||
|
||||
for(uint x=start; x<stop; x++)
|
||||
{
|
||||
Complex s(sound.at(x));
|
||||
double angle=-2*PI*f*x/8000;
|
||||
s*= Complex( cos(angle) , sin(angle) );
|
||||
c+=s;
|
||||
}
|
||||
result[f]= c.Mod()/(stop-start) ;
|
||||
}
|
||||
return result;*/
|
||||
}
|
||||
|
||||
bool VoiceSignature::window(const Sound& sound, unsigned int *_start, unsigned int *_stop)
|
||||
{
|
||||
bool isNoise=false;
|
||||
unsigned int length=sound.size();
|
||||
uint unit=WINDOW_UNIT;
|
||||
if(length < unit )
|
||||
return false;
|
||||
|
||||
//Fenêtrage
|
||||
unsigned int start=0 , stop=0;
|
||||
double moy=0;
|
||||
for(uint x=0;x<unit;x++)
|
||||
{
|
||||
moy+=ABS(sound.at(x));
|
||||
}
|
||||
|
||||
if(moy>WINDOW_MINIMUM*unit)
|
||||
isNoise=true;
|
||||
|
||||
for(uint x=unit; x<length; x++)
|
||||
{
|
||||
if(moy<WINDOW_MINIMUM*unit)
|
||||
{
|
||||
if(stop==0)
|
||||
start=x-unit/2;
|
||||
}
|
||||
else
|
||||
stop=x-unit/2;
|
||||
moy+=ABS(sound.at(x));
|
||||
moy-=ABS(sound.at(x-unit));
|
||||
|
||||
}
|
||||
|
||||
if(moy>WINDOW_MINIMUM*unit && isNoise)
|
||||
return false;
|
||||
|
||||
stop=MIN(length,stop+WINDOW_MINIMUM_ECART);
|
||||
start=MAX(0 ,start-WINDOW_MINIMUM_ECART);
|
||||
|
||||
if(_start)
|
||||
*_start=start;
|
||||
if(_stop)
|
||||
*_stop=stop;
|
||||
return start<stop;
|
||||
}
|
||||
|
||||
//finally doesn't give better results
|
||||
/*#define HZ_TO_MEL(F) (1127*log(1+(F)/700.0))
|
||||
#define MEL_TO_HZ(M) ( ( exp((M)/1127.0) -1) *700 )*/
|
||||
#define HZ_TO_MEL(F) (F)
|
||||
#define MEL_TO_HZ(F) (F)
|
||||
|
||||
|
||||
VoiceSignature::VoiceSignature(const Sound& sound)
|
||||
{
|
||||
static uint temp_wind=0, temp_fft=0, temp_moy=0;
|
||||
QTime t;
|
||||
t.start();
|
||||
|
||||
unsigned int start , stop;
|
||||
if(!window(sound,&start,&stop))
|
||||
{
|
||||
kWarning() << "No voice found in the sound" ;
|
||||
return;
|
||||
}
|
||||
|
||||
temp_wind+=t.restart();
|
||||
|
||||
uint length=stop-start;
|
||||
|
||||
for(int wind=0; wind<WINDOW_NUMBER; wind++)
|
||||
{
|
||||
unsigned int w_start=MAX(start, start+ (int)((wind - WINDOW_SUPER)*length/WINDOW_NUMBER));
|
||||
unsigned int w_stop =MIN(stop , start+ (int)((wind+1.0+WINDOW_SUPER)*length/WINDOW_NUMBER));
|
||||
|
||||
|
||||
QVector<double> fourrier=fft(sound, w_start,w_stop);
|
||||
|
||||
temp_fft+=t.restart();
|
||||
|
||||
//MEL conversion
|
||||
double mel_start=HZ_TO_MEL(FFT_RANGE_INF);
|
||||
uint mel_stop=HZ_TO_MEL(FFT_RANGE_SUP);
|
||||
|
||||
for(int four=0; four<FOUR_NUMBER; four++)
|
||||
{
|
||||
unsigned int wf_start=mel_start + four*(mel_stop-mel_start)/FOUR_NUMBER;
|
||||
unsigned int wf_stop=mel_start + (four+1)*(mel_stop-mel_start)/FOUR_NUMBER;
|
||||
|
||||
unsigned int f_start=MEL_TO_HZ( wf_start )*fourrier.size()/sound.fs();
|
||||
unsigned int f_stop=MEL_TO_HZ( wf_stop )*fourrier.size()/sound.fs();
|
||||
unsigned int f_size=f_stop-f_start;
|
||||
|
||||
double nb=0;
|
||||
for(uint f=f_start; f<f_stop; f++)
|
||||
{
|
||||
int freq=f*fourrier.size()/sound.fs();
|
||||
nb+=fourrier[f]*FFT_PONDERATION(freq);
|
||||
}
|
||||
nb/=(f_size);
|
||||
data[wind][four]=nb;
|
||||
}
|
||||
|
||||
temp_moy+=t.restart();
|
||||
|
||||
}
|
||||
|
||||
// kDebug() << "wind: "<< temp_wind << " - fft: " << temp_fft << " - moy: " << temp_moy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VoiceSignature::~VoiceSignature()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
float VoiceSignature::diff(const VoiceSignature &s1, const VoiceSignature &s2)
|
||||
{
|
||||
if(s1.isNull() || s2.isNull())
|
||||
return 1000000;
|
||||
#if 0
|
||||
double result=0;
|
||||
for(int x=0;x<WINDOW_NUMBER;x++)
|
||||
for(int y=0;y<FOUR_NUMBER;y++)
|
||||
{
|
||||
double d1=s1.data[x][y]-s2.data[x][y];
|
||||
result+= d1*d1;//*pond[x][y];
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
|
||||
//DTW
|
||||
// http://tcts.fpms.ac.be/cours/1005-08/speech/projects/2001/delfabro_henry_poitoux/
|
||||
|
||||
const int I=WINDOW_NUMBER;
|
||||
const int J=WINDOW_NUMBER;
|
||||
double g[I+1][J+1];
|
||||
for(int f=1;f<=J;f++)
|
||||
g[0][f]=10000000;
|
||||
for(int f=1;f<=I;f++)
|
||||
g[f][0]=10000000;
|
||||
g[0][0]=0;
|
||||
for(int i=1;i<=I;i++)
|
||||
for(int j=1;j<=J;j++)
|
||||
{
|
||||
double d=0;
|
||||
for(int f=0;f<FOUR_NUMBER;f++)
|
||||
{
|
||||
double d1=s1.data[i-1][f]-s2.data[j-1][f];
|
||||
d+= d1*d1;//*pond[x][y];
|
||||
}
|
||||
d=sqrt(d);
|
||||
g[i][j]=qMin(qMin( g[i-1][j]+d, g[i][j-1]+d ) , g[i-1][j-1]+d+d );
|
||||
}
|
||||
|
||||
return g[I][J]/(I+J);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int VoiceSignature::size1()
|
||||
{
|
||||
return WINDOW_NUMBER;
|
||||
}
|
||||
|
||||
int VoiceSignature::size2()
|
||||
{
|
||||
return FOUR_NUMBER;
|
||||
}
|
||||
|
||||
QMap<int, QMap<int, double> > VoiceSignature::pond;
|
||||
|
||||
|
||||
|
||||
void VoiceSignature::write(KConfigGroup& cfg, const QString &key) const
|
||||
{
|
||||
QStringList sl;
|
||||
for(int x=0;x<WINDOW_NUMBER;x++)
|
||||
for(int y=0;y<FOUR_NUMBER;y++)
|
||||
{
|
||||
sl.append( QString::number(data[x][y]) );
|
||||
}
|
||||
cfg.writeEntry(key,sl);
|
||||
}
|
||||
|
||||
void VoiceSignature::read(KConfigGroup& cfg, const QString &key)
|
||||
{
|
||||
QStringList sl=cfg.readEntry(key, QStringList());
|
||||
for(int x=0;x<WINDOW_NUMBER;x++)
|
||||
for(int y=0;y<FOUR_NUMBER;y++)
|
||||
{
|
||||
data[x][y]= sl[x*FOUR_NUMBER+y].toDouble();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2005 by Olivier Goffart *
|
||||
* ogoffart@kde.org *
|
||||
* *
|
||||
* 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, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef SIGNATURE_H
|
||||
#define SIGNATURE_H
|
||||
|
||||
|
||||
#include <QVector>
|
||||
#include <QtCore/QMap>
|
||||
#include <kdemacros.h>
|
||||
#include <KConfig>
|
||||
|
||||
class Sound;
|
||||
|
||||
|
||||
#define WINDOW_MINIMUM 0.10
|
||||
#define WINDOW_MINIMUM_ECART 200
|
||||
#define WINDOW_NUMBER 7
|
||||
#define WINDOW_SUPER 0.43
|
||||
#define WINDOW_UNIT sound.fs()/4
|
||||
#define FOUR_NUMBER 7
|
||||
#define FOUR_SUPER 0
|
||||
|
||||
|
||||
#define FFT_RANGE_INF 370
|
||||
#define FFT_RANGE_SUP 2000
|
||||
// #define FFT_PONDERATION(f) ((double)log(1+(f))/log(10))
|
||||
#define FFT_PONDERATION(f) 1
|
||||
|
||||
|
||||
// theses settings are better in a 8000Hz fs
|
||||
/*#define FFT_RANGE_INF 300
|
||||
#define FFT_RANGE_SUP 1500*/
|
||||
|
||||
|
||||
//#define REJECT_FACTOR_ECART_REL 0.5
|
||||
#define REJECT_FACTOR_DIFF 0.0018
|
||||
|
||||
|
||||
|
||||
#define HAMMING false
|
||||
|
||||
|
||||
|
||||
|
||||
namespace KHotKeys
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
@author Olivier Goffart
|
||||
*/
|
||||
class KDE_EXPORT VoiceSignature{
|
||||
public:
|
||||
explicit VoiceSignature(const Sound& s);
|
||||
|
||||
VoiceSignature(){}
|
||||
~VoiceSignature();
|
||||
|
||||
QMap<int, QMap<int, double> > data;
|
||||
|
||||
static QMap<int, QMap<int, double> > pond;
|
||||
|
||||
static float diff(const VoiceSignature &s1, const VoiceSignature &s2);
|
||||
|
||||
|
||||
static int size1();
|
||||
static int size2();
|
||||
|
||||
|
||||
static QVector<double> fft(const Sound& sound, unsigned int start, unsigned int stop);
|
||||
static bool window(const Sound& sound, unsigned int *start, unsigned int *stop);
|
||||
|
||||
void write(KConfigGroup& cfg, const QString &key) const;
|
||||
void read(KConfigGroup& cfg, const QString &key);
|
||||
|
||||
inline bool isNull() const
|
||||
{
|
||||
return data.isEmpty();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue