das Menü habe ich doch schon gebastelt, ohne ncurses.
Druckbare Version
das Menü habe ich doch schon gebastelt, ohne ncurses.
So mein Freund. Mein Spieltrieb ist durchaus entzückt. Hier das Ergebnis:
main.cpp
diasound.hppCode:#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <stdio.h>
#include <limits.h>
#include <math.h>
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <fontinfo.h>
#include <shapes.h>
using namespace std;
string version = "2.1";
string _speicher = "leer";
string _status = "ungesichert";
string _datei = "";
string _fehler = "";
#include "diaSound.hpp"
#include "menu.hpp"
#define BLACK 0, 0, 0
#define WHITE 255, 255, 255
#define MAGENTA 255, 0, 255
#define RED 255, 0, 0
#define YELLOW 255, 255, 0
#define LIME 0, 255, 0
#define GREEN 0, 128, 0
#define CYAN 0, 255, 255
#define AQUA 102, 204, 204
#define BLUE 0, 0, 255
int _width_=1024, _height_=600;
int _fontsize_ = 10;
bool ausgabe = true;
void initOpenVG()
{
initWindowSize(0, 0, _width_, _height_);
init(&_width_, &_height_);
Start(_width_, _height_);
Background(0, 0, 0);
StrokeWidth(1.0);
WindowClear();
}
void plotArray(int32_t *array, int32_t arrlength, int y0)
{
float xscale=1.0, border=100.0;
xscale = _width_ / (float) (arrlength-border);
int i;
Fill(CYAN, 1);
Stroke(0, 255, 255, 1);
for(i=0;i<arrlength;i++)
{
Line((VGfloat)xscale*i, (VGfloat) y0, (VGfloat)xscale*i, (VGfloat)(y0+array[i]));
}
End();
}
void analyse(int32_t *array, int32_t arrlength)
{
int32_t sbuf[128];
int32_t bias, minr, maxr, baseline,
signalstart, signalend;
int32_t maximum = array[0];
int32_t minimum = array[0];
int32_t maxpos, minpos;
int32_t i;
for(i=0;i<arrlength;i++)
{
if(array[i] > maximum)
{
maximum = array[i];
maxpos = i;
}
if(array[i] < minimum)
{
minimum = array[i];
minpos = i;
}
}
maximum = array[0];
minimum = array[0];
for(i=0;i<arrlength; ++i)
{
if(array[i] > maximum)
{
maximum = array[i];
maxpos = i;
}
if(array[i] < minimum)
{
minimum = array[i];
minpos = i;
}
}
// calculate baseline from last 100 array cells:
// init vars
baseline=(array[minpos] + array[maxpos]) / 2; // init baseline by (min+max)/2
minr=baseline - 1;
maxr=baseline + 1;
// auto-adjust:
for(i=arrlength-100; i<arrlength; ++i)
{
// mean baseline
baseline = round((0.5*(float)array[i] + 0.5*(float)baseline)) ;
// smoothed out max noise
if(array[i] >= baseline) maxr = round((0.6*(float)array[i] + 0.4*(float)maxr)) +1 ;
// smoothed out min noise
if(array[i] <= baseline) minr = round((0.6*(float)array[i] + 0.4*(float)minr)) -1 ;
}
bias = max(baseline-minr, maxr-baseline) +1;
// noise reduction start/end
// drop small noise
for(i=0;i<arrlength;++i)
{
if((array[i]>baseline) && (array[i] <= baseline + bias)) array[i] = baseline ; // little higher value => drop to baseline
else
if((array[i]<baseline) && (array[i] >= baseline - bias)) array[i] = baseline ; // little lower value => rise to baseline
}
// signalstart, signalend: threshold = bias + (bias/2)
signalstart = 0;
i = 0;
while((array[i]<=baseline + 4 * bias/3) && (i<SHRT_MAX-1)) ++i;
signalstart = i;
if(i > 0) signalstart -= 1;
signalend=arrlength-1;
i=arrlength-1;
while((array[i]<=baseline + + 4*bias/3) && (i>signalstart)) --i;
signalend = i;
if(i<arrlength-1) signalstart +=1;
if(ausgabe)
{
cout << "Bias: " << bias << endl;
cout << "Maximal: " << maximum << endl;
cout << "Minimal: " << minimum << endl;
cout << "Signalstart: " << signalstart << endl;
cout << "Signalende: " << signalend << endl;
}
}
int main(int argc, char *argv[])
{
fstream datei;
string dateiEndung;
string dateiName;
int32_t waveBuffer[SHRT_MAX];
int32_t i, menuRet;
char s[3], m[3];
initOpenVG();
menuRet = menu(0, 0);
while(menuRet != -1)
{
switch(menuRet)
{
case 0:
datei.open(_datei, ios::in);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei >> waveBuffer[i];
}
datei.close();
plotArray(waveBuffer, SHRT_MAX, 0);
_speicher = "Wave vorhanden";
_status = "gesichert";
}
else _fehler = "Datei konnte nicht geöffnet werden!";
break;
case 1:
audioCapture(waveBuffer, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
_speicher = "Wave vorhanden";
_status = "ungesichert";
_datei = "";
break;
case 2:
datei.open(_datei, ios::in);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei >> waveBuffer[i];
}
datei.close();
_speicher = "Wave vorhanden";
_status = "gesichert";
playCaptured(waveBuffer, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
}
else _fehler = "Datei konnte nicht geöffnet werden!";
break;
case 3:
playCaptured(waveBuffer, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
break;
case 5:
dateiEndung = ".hhw";
dateiName = _datei + dateiEndung;
datei.open(dateiName, ios::out);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei << waveBuffer[i] << endl;
}
datei.close();
_status = "gesichert";
}
else _fehler = "Die Datei konnte nicht geöffnet werden!";
break;
case -1:
return 1;
break;
}
menuRet = menu(0, 0);
}
/*
plotArray(waveBuffer, SHRT_MAX, 0);
analyse(waveBuffer, SHRT_MAX);
plotArray(waveBuffer, SHRT_MAX, 255);
SaveEnd("plott.raw");
finish();
*/
return 1;
}
menu.hppCode:#include <alsa/asoundlib.h>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
typedef struct _FILE_head
{
unsigned char ID[4];
unsigned int Length;
unsigned char Type[4];
} FILE_head;
typedef struct _FORMAT
{
short wFormatTag;
unsigned short wChannels;
unsigned int dwSamplesPerSec;
unsigned int dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} FORMAT;
typedef struct _CHUNK_head
{
unsigned char ID[4];
unsigned int Length;
} CHUNK_head;
snd_pcm_t *soundKarte;
bool Init(string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
int err;
snd_pcm_format_t bits;
unsigned int resample = 1;
switch(WaveBits)
{
case 8:
bits = SND_PCM_FORMAT_U8;
break;
case 16:
bits = SND_PCM_FORMAT_S16;
break;
case 24:
bits = SND_PCM_FORMAT_S24;
break;
case 32:
bits = SND_PCM_FORMAT_S32;
break;
}
snd_pcm_hw_params_t *hw_params;
if(name.length() == 0)
{
err = snd_pcm_open(&soundKarte, "plughw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
}
else
{
err = snd_pcm_open(&soundKarte, name.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
}
if(err < 0)
{
_fehler = "Init: Kann die Soundkarte nicht öffnen!";
return false;
}
if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
_fehler = "Init: Parameter können nicht initialisiert werden!";
return false;
}
if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
{
_fehler = "Init: Parameter können nicht ermittelt werden!";
return false;
}
err = snd_pcm_hw_params_set_rate_resample(soundKarte, hw_params, resample);
if(err < 0)
{
_fehler = "Init: Resampling kann nicht eingeschaltet werden!";
return err;
}
if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
_fehler = "Init: Zugriffstyp kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
{
_fehler = "Init: Sample-Format kann nicht gesetzt werden!";;
return false;
}
if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
{
_fehler = "Init: Anzahl der Kanäle kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
{
_fehler = "Init: Sample-Rate kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
{
_fehler = "Init: Parameters können nicht gesetzt werden!";
return false;
}
snd_pcm_hw_params_free(hw_params);
if((err = snd_pcm_prepare(soundKarte)) < 0)
{
_fehler = "Init: Audio kann nicht zur Nutzung vorbereitet werden!";
return false;
}
return true;
}
bool InitCapture(string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
int err;
snd_pcm_format_t bits;
switch(WaveBits)
{
case 8:
bits = SND_PCM_FORMAT_U8;
break;
case 16:
bits = SND_PCM_FORMAT_S16;
break;
case 24:
bits = SND_PCM_FORMAT_S24;
break;
case 32:
bits = SND_PCM_FORMAT_S32;
break;
}
snd_pcm_hw_params_t *hw_params;
if(name.length() == 0)
{
err = snd_pcm_open(&soundKarte, "plughw:1,0", SND_PCM_STREAM_CAPTURE, 0);
}
else
{
err = snd_pcm_open(&soundKarte, name.c_str(), SND_PCM_STREAM_CAPTURE, 0);
}
if(err < 0)
{
_fehler = "Init: Kann die Soundkarte nicht öffnen!!";
return false;
}
if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
_fehler = "Init: Parameter können nicht initialisiert werden!";
return false;
}
if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
{
_fehler = "Init: Parameter können nicht ermittelt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
_fehler = "Init: Zugriffstyp kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
{
_fehler = "Init: Sample-Format kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
{
_fehler = "Init: Anzahl der Kanäle kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
{
_fehler = "Init: Sample-Rate kann nicht gesetzt werden!";
return false;
}
if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
{
_fehler = "Init: Parameters können nicht gesetzt werden!";
return false;
}
snd_pcm_hw_params_free(hw_params);
if((err = snd_pcm_prepare(soundKarte)) < 0)
{
_fehler = "Init: Audio kann nicht zur Nutzung vorbereitet werden!";
return false;
}
return true;
}
bool UnInit()
{
snd_pcm_close(soundKarte);
return true;
}
int playwave(string waveDatei, string name)
{
FORMAT format;
FILE_head head;
CHUNK_head chead;
char *wave;
register snd_pcm_uframes_t count, frames;
int datei;
unsigned int WaveSize;
datei = open(waveDatei.c_str(), 00);
read(datei, &head, sizeof(FILE_head));
read(datei, &chead, sizeof(CHUNK_head));
read(datei, &format, sizeof(FORMAT));
wave = (char *) malloc(head.Length);
read(datei, wave, head.Length);
WaveSize = head.Length * 8 / ((unsigned int)format.wBitsPerSample * (unsigned int)format.wChannels);
close(datei);
Init(name, format.wChannels, format.dwSamplesPerSec, format.wBitsPerSample);
count = 0;
do
{
frames = snd_pcm_writei(soundKarte, wave + count, WaveSize - count);
if (frames < 0) frames = snd_pcm_recover(soundKarte, frames, 0);
if (frames < 0)
{
printf("Kann wav nicht abspielen: %s\n", snd_strerror(frames));
break;
}
count += frames;
} while (count < WaveSize);
if (count == WaveSize) snd_pcm_drain(soundKarte);
free(wave);
UnInit();
return 0;
}
void audioCapture(int32_t *input, int max, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
int err, i=0;
int32_t *puffer;
puffer = (int32_t *) malloc(1);
if(InitCapture(name, channels, actualRate, WaveBits))
{
while(i < max)
{
err = snd_pcm_readi(soundKarte, puffer, 1);
if(err < 0) _fehler = "Fehler bei der Aufnahme!";
input[i] = puffer[0];
i++;
}
free(puffer);
UnInit();
}
else _fehler = "Bei der Initialisierung ist ein Fehler aufgetreten!";
}
void playCaptured(int32_t *array, unsigned int WaveSize, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
register snd_pcm_uframes_t count, frames;
uint8_t *wave;
wave = (uint8_t *) malloc(WaveSize+1);
for(int32_t i=0;i<WaveSize;i++) wave[i] = array[i];
Init(name, channels, actualRate, WaveBits);
WaveSize = WaveSize * 8 / WaveBits * channels;
count = 0;
do
{
frames = snd_pcm_writei(soundKarte, wave + count, WaveSize - count);
if(frames < 0) frames = snd_pcm_recover(soundKarte, frames, 0);
if(frames < 0)
{
_fehler = "Kann wav nicht abspielen";;
break;
}
count += frames;
} while (count < WaveSize);
if (count == WaveSize) snd_pcm_drain(soundKarte);
UnInit();
}
Da gibts doch jetzt nichts mehr zu meckern ;). Jetzt gehts dann ans optimieren usw.Code:#include <ncurses.h>
#include <dirent.h>
void quit()
{
endwin();
}
int subMenu(int32_t menu, string text)
{
WINDOW *w;
DIR *d;
struct dirent *dir;
int32_t i, ch, posMenu, max, start, ende, z;
vector<string> dateien;
switch(menu)
{
case 0:
w = newwin(16, 19, 4, 29);
scrollok(w, true);
keypad(w, TRUE);
wbkgd(w, COLOR_PAIR(1));
box(w, 0, 0);
d = opendir(".");
if(d)
{
while((dir = readdir(d)) != NULL)
{
if(strstr(dir->d_name, ".hhw")) dateien.push_back(dir->d_name);
}
closedir(d);
}
ende = dateien.size() - 1;
if(dateien.size() > 14) max = 14;
else max = dateien.size();
for(i=0;i<max;i++)
{
if(i == 0)
{
wattron(w, A_STANDOUT);
mvwprintw(w, i+1, 1, "%-17s", dateien[i].c_str());
wattroff(w, A_STANDOUT);
}
else mvwprintw(w, i+1, 1, "%-17s", dateien[i].c_str());
}
start = 0;
while(ch = wgetch(w))
{
switch(ch)
{
case KEY_UP:
posMenu--;
if(posMenu < 0) posMenu = 0;
if(posMenu == start && posMenu > 0)
{
start--;
max--;
}
break;
case KEY_DOWN:
if(posMenu < ende) posMenu++;
if(posMenu == max && posMenu < ende)
{
start++;
max++;
}
break;
case 10:
_datei = dateien[posMenu];
return 1;
break;
}
clear();
for(i=start,z=1;i<max;i++,z++)
{
if(i == posMenu)
{
wattron(w, A_STANDOUT);
mvwprintw(w, z, 1, "%-17s", dateien[i].c_str());
wattroff(w, A_STANDOUT);
}
else
{
mvwprintw(w, z, 1, "%-17s", dateien[i].c_str());
}
}
wrefresh(w);
}
wrefresh(w);
return 0;
break;
case 1:
w = newwin(5, 18, 4, 30);
wbkgd(w, COLOR_PAIR(1));
box(w, 0, 0);
mvwprintw(w, 1, 2, text.c_str());
wrefresh(w);
return 1;
break;
case 5:
w = newwin(4, 29, 11, 30);
char inputDatei[20];
wbkgd(w, COLOR_PAIR(1));
box(w, 0, 0);
mvwprintw(w, 1, 2, "Dateiname zum Speichern");
mvwprintw(w, 2, 2, "->");
move(2, 5);
curs_set(1);
mvwgetnstr(w, 2, 5, inputDatei, 14);
_datei = inputDatei;
wrefresh(w);
return 1;
break;
}
return -1;
}
int menu(int32_t menu, int32_t posMenu)
{
char mainMenu[7][20] = {"Datei laden", "Wave aufnehmen", "Datei abspielen", "Speicher abspielen", "Speicher optimieren", "Speicher sichern", "Beenden"};
int32_t i, ch;
initscr();
atexit(quit);
curs_set(0);
start_color();
clear();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
bkgd(COLOR_PAIR(1));
border(0, 0, 0, 0, 0, 0, 0, 0);
mvhline(2, 0, ACS_LTEE, 1);
mvhline(2, 1, ACS_HLINE, 78);
mvhline(2, 79, ACS_RTEE, 1);
mvhline(21, 0, ACS_LTEE, 1);
mvhline(21, 1, ACS_HLINE, 78);
mvhline(21, 79, ACS_RTEE, 1);
mvprintw(1, 3, "HaWe und Hirnfrei\'s Soundprojekt V %s", version.c_str());
mvprintw(22, 3, "Meldung: %s", _fehler.c_str());
refresh();
WINDOW *w, *sw;
sw = newwin(5, 28, 4, 50);
wbkgd(sw, COLOR_PAIR(1));
box(sw, 0, 0);
mvwprintw(sw, 1, 2, "Speicher: %-15s", _speicher.c_str());
mvwprintw(sw, 2, 2, "Status: %-15s", _status.c_str());
mvwprintw(sw, 3, 2, "Datei: %-15s", _datei.c_str());
wrefresh(sw);
w = newwin(15, 25, 4, 2);
wbkgd(w, COLOR_PAIR(1));
box(w, 0, 0);
keypad(w, TRUE);
for(i=0;i<7;i++)
{
if(i == posMenu)
{
wattron(w, A_STANDOUT);
mvwprintw(w, i+1, 2, "%s", mainMenu[i]);
wattroff(w, A_STANDOUT);
}
else
{
mvwprintw(w, i+1, 2, "%s", mainMenu[i]);
}
}
wrefresh(w);
while(ch = wgetch(w))
{
switch(ch)
{
case KEY_UP:
posMenu--;
if(posMenu < 0) posMenu = 6;
break;
case KEY_DOWN:
posMenu++;
if(posMenu > 6) posMenu = 0;
break;
case 10:
switch(posMenu)
{
case 0:
if(subMenu(0, "") == 1) return 0;
break;
case 1:
if(subMenu(1, "Aufzeichnung...") == 1) return 1;
break;
case 2:
if(subMenu(0, "") == 1) return 2;
break;
case 3:
if(subMenu(1, "Spiele ab...") == 1) return 3;
break;
case 5:
if(_speicher.compare("leer") != 0) if(subMenu(5, "") == 1) return 5;
break;
case 6:
return -1;
break;
}
break;
}
for(i=0;i<7;i++)
{
if(i == posMenu)
{
wattron(w, A_STANDOUT);
mvwprintw(w, i+1, 2, "%s", mainMenu[i]);
wattroff(w, A_STANDOUT);
}
else
{
mvwprintw(w, i+1, 2, "%s", mainMenu[i]);
}
}
wrefresh(w);
}
}
Hast du mittlerweile eine Soundkarte usw? Kannst du auch Sounds aufnehmen und abspielen?
Die alten csv Dateien kannst du damit auch abspielen, musst sie nur in .hhw (HaWe - Hirnfrei - Wave ^^) umbenennen.
- - - Aktualisiert - - -
Nebenbei, ich baue gerade das Plotten etwas um, so dass es in einem Fenster dargestellt wird und nicht so dumm auf den Screen geschrieben wird. Das sollte keine grosse Geschichte sein und macht die Sache etwas komfortabler.
hallo,
nein, habe noch keine soundcard, und auch noch kein ncurses installiert.
Leider durchblicke ich dein Menü nicht, es ist - nun - etwas - uummmh - deutlich - ääähh - aufgeblähter als meins ;)
0 Soundfile *.csv in Programm öffnen / laden \n
1 Soundfile *.wav in Programm öffnen / laden \n
2 Soundfile *.wav öffnen / abspielen + Plot \n
3 Sound aufnehmen per Micro / SoundCard \n
4 akt. Sound (Array im RAM) abspielen + Plot \n
5 akt. Sound optimieren (noise/cut) \n
6 akt. Sound (im RAM) als *.wav File speichern unter... \n
7 akt. Sound an FFT + Plot \n
8 akt. Sound cross correlation mit 1 wav File \n
9 akt. Sound cross correlation mit allen *.wav Files (auto) \n\n
kann es denn schon alles wie geplant (0-6, 7-9 kommt ja erst noch) ?
aber dann hast du sicher schon die 3 geplanten Grundwörter aufgenommen und optimiert ? 8)
ps,
ich finde noch keine Funktion, um einen sound-array als *.wav zu speichern - wie heißt die bei dir?
Die heisst "Gibts nicht".
Ja ist etwas aufgeblähter, funktioniert dafür super ^^. Samt eventueller Fehlermeldungen usw.
Was bisher funktioniert:
0, 1 ist bei mir der erste Menüpunkt "Datei laden". Da zeigt sich dann in der Mitte vom Menü eine Auswahl alles vorhandenen Dateien (also alle hhw Dateien), sogar scrollbar. Da wird die Datei nur in den Speicher geschrieben und kann dann nach Belieben weiter verarbeitet werden. Derzeit also abspielen, optimieren und speichern.
2 ist bei mir "Datei abspielen" und funktioniert wie 0-1 nur das die Datei eben sofort nach dem Laden auch abgespielt wird.
3 ist bei mir "Wave aufnehmen". Die Daten von der Soundkarte werden in das array geschrieben und liegen im Speicher. Wie beim Laden kann man damit dann auch alles Mögliche damit machen. Abspielen, optimieren, speichern...
4 ist bei mir "Speicher abspielen. Spielt schon prima ab, plottet aber noch nicht weil ich das noch in ein Fenster packen will. Ich weiss nicht aber so direkt in den Bildschirm schreiben fühlt sich irgendwie "falsch" an.
5 Optimieren habe ich zu meiner Schande vergessen einzubauen. Der Menüpunkt ist da aber ich hab vergessen ihn funktionsfähig zu machen :(
6 ist bei mir "Speicher sichern". Wählt man das an wird man zur Eingabe eines Dateinamens aufgefordert. Die Dateiendung wird automatisch hinzugefügt.
7-9 füge ich dann noch hinzu.
Lach nee ich hab die Worte noch nicht aufgenommen.
openVG schreibt immer direkt in den Fensterbereich, es hat nunmal keine XWindows Funktion.
Ich habe bei mir immer einen openVG Fenster-Bereich für die Grafiken neben einem Terminal-Fenster für die Schrift-Ausgabe (ohne ncurses).
Von ncurses bin ich einfach nicht überzeugt, es funktionieren dort einfach die normalen printf Befehle nicht korrekt (\n etc), und deshalb nutze ich es nicht.
Brauchst ja nicht damit zu programmieren, reicht ja wenn du es benutzt oder ^^.
OpenVG schreibt direkt in die GPU, bzw. dessen Speicher. Das kann man aber anscheinend auch in ein Fenster leiten, was die Sache angenehmer macht wie ich finde.
wie unterscheidet das Programm, ob es einen .wav File oder einen .csv File lädt?
- - - Aktualisiert - - -
ps,
Datei laden und abspielen muss man trennen -
es muss abspielen möglich sein (z.B. zum Test), ohne dass die wave Daten ins Programm geladen werden!
Warum sollte man ein wav laden? Ich verstehe deine Affinität zu wav Dateien nicht wirklich :(.
Achso. Okay das baue ich um ist kein Ding.
wav ist das universelle Standard-Datenformat für sounds, es werden daher grundsätzlich *.wav gespeichert und geladen.
Die *.wav Files kann man dann auch mit unabhängigen Programmen abhören (und auch bearbeiten), z.B. mit Omxplayer oder mit Windows wave-edit-Programmen.
Ich weiss was wav ist. So ganz dämlich bin ich dann ja doch nicht.
Okay dann kann man sie in einem anderen Programm abspielen. Leuchtet ein, nur warum sollte man das tun? Man kann sie in unserem Programm ja schliesslich auch abspielen. Und in einem anderen Programm bearbeiten leuchtet auch ein, aber da nochmal die Frage nach dem Grund. Ich meine, wenn ich mich nicht irre soll ja unser Programm am Ende ganz alleine das Wort verstehen. Dann sollte das Programm mit der notwendigen Bearbeitung ja auch zurecht kommen oder?
Fenster lasse ich doch erstmal bleiben. Ich denke da du wahrscheinlich nach wie vor auf dem Raspi das schwache LXDE benutzt wäre der Installationsaufwand zu gross.
Es ist im Moment von mir als ein Regie-Programm zur Vorbereitung und zum Test gedacht, mit universellen Schnittstellen zu Standard-Datenformaten, und das heißt:
*.wav - Standard.
Das "echte" Spracherkennungsprogramm wird das sein, das danach kommt und auf den Tests des Regieprogramms aufbaut... ;)
Trotzdem werden Sounds immer als wav gespeichert und wieder geladen, niemals anders, sonst ist es nicht mehr Standard-kompatibel über verschiedene Plattformen hinweg (z.B. auch für die Anwendung externer Sound-Filter).
Du sagst es ja. Es ist ein "Regie-Programm". Warum muss das über verschiedene Plattformen hinweg kompatibel sein?
Bleibt das Plotten jetzt in einer Spur oder wird mehr auf einem Bildschirm geplottet?
zum Plotten:
es wäre vlt gut, wenn wir später verschiedene Plots vergleichen könnten, also dann 2-3 untereinander, ich weiß noch nicht, was auf uns zu kommt:
vlt auch oben ein Sound-Plot, darunter der FFT-Graph.
oder 2 Sounds und 2 FFT-Graphen.
Eine variable Basis-Null-Linie (x-Achse) macht die Sache sicher sehr übersichlich.
zum Regie-Programm:
auch da weiß ich noch nicht, ob wir mit der FFT und dem "Roh-Sound" Erfolg haben, gerade wenn ich spreche und deine Muster verwende, oder auch wenn verschieden starke Störungen dabei sind, oder wenn Wörter verschieden schnell gesprochen werden.
Auch was die FFT draus macht, kann ich nur grob erahnen.
Bisher haben wir ja nur die Möglichkeit, Bereiche vorher/nachher abzuschneiden - der Klang an sich wurde nicht verändert.
Es kann also heißen, daß die Vielzahl an Begleit-Frequenzen reduziert werden muss durch Hoch- oder Tiefpassfilter, damit der signifikante Bereich möglichst prägnant herausgestellt wird und unwichtige Frequenzen eliminiert werden.
Keine Ahnung, welche das sein werden - hohe Frequenzen können durchaus wichtig sein (Zisch- oder harte "t"-Laute oder Gutturale etc. ) - trotzdem mag es sein, dass die tiefen Anteile des Klangs (z.B. bis 1000 Hz) ausreichend sind.
Je nachdem, wie die CC Ergebnisse sind, muss man also mit den Klängen experimentieren, aber dafür einen eigenen Equalizer noch zu programmieren, ist sicher etwas hoch gegriffen.
Daher die Option, dafür zunächst externe wav-edit-Programme verwenden zu können bzw. können zu müssen.
Was mir eben nicht so gefällt ist dieses Statische beim direkt in den Grafikspeicher schreiben. Man kann es nicht verschieben und gar nichts. Das ist so gar nicht mein Ding. Okay wenn man nur eine Anzeige hat die man danach eh wieder weg klickt von mir aus, aber wenn man das länger verwenden will ist der Teil vom Bildschirm ja futsch. Unschön. GTK wäre da eben eine nette Lösung gewesen, dafür gibt es auch Beispiele, aber dann müsstest du dir erstmal das komplette GTK 3 plus dev installieren. Das ist wohl übertrieben.
Ich habe aber noch die Möglichkeiten von OpenWF und OpenCV gefunden. Das könnte eine Möglichkeit sein. Mit OpenCV arbeite ich ja sowieso wegen Gesichtserkennung usw. Mal schauen was da geht. Wäre in meinen Augen angenehmer, wenn man das Bild auch in den Hintergrund schicken kann bei Bedarf.
Hast du eigentlich das mit fftw.org gesehen?
sorry, bitte bleibe bei den Tools, so wie vereinbart, ich werde nichts anderes installieren als mein jetziges openVG, also auch kein openCV.
Ich muss schließlich das Programm und seine einzelnen API-Tools auch selber verwenden und die Tools entsprechend selber weiter programmieren können.
Dazu muss ich die Funktionen kennen und selber nutzen können.
Für andere FFT-Funktionen als die von mir verlinkte sehe ich auch keinen Zusatz-Nutzen - wozu also wechseln? Die Cross-Correlation wird als Herausforderung schwierig genug werden. Es ist ja komplettes Neuland für mich, ich muss mich da selber Schritt für Schritt langsam einarbeiten und hineinfinden. Bei zuviel neuen Dingen verliere ich den Überblick.
Ich habe mich inzwischen deshalb auch gegen ncurses entschieden, weil ich mich dann in dem Menü nicht mehr zurechtfinde, und außerdem sind ncurses-Fenster für andere Ausgabefunktonen nicht mehr stdio.h-kompatibel, so wie es das LXTerminal-Window ist. Nur für diese einmalige simple Auswahl 0...9 eine inkompatible Monsterlib zu installieren, die ich später nicht mehr weiter verwende, ist für mich ein unwirtschaftlicher und nicht angemessener Aufwand.
Was in 5 oder 6 Jahren mal sein wird, weiß ich ntl nicht, da kann ich durchaus so weit sein, dass ich auch möglicherweise mal openCV und ncurses verwenden könnte.
Ich brauche als gemeinsame Regie-Schnittstelle auch genau das Menü, das ich oben bereits vorprogrammiert und dir gepostet hatte.
Ich bin kein Linux-Programmierer, ich programmiere auf MSDOS- TurboC oder Arduino-IDE-Niveau, und ich verwende selber auch kein C++, sondern ausschließlich ANSI C.
Daher auch meine absolute Abneigung genüber Vektoren und strings, stattdesen: char * array[size].
Wenn mir das Programm zu kompliziert und von der Syntax her zu fremd ist, kann ich es selber später nicht mehr für meine eigenen Spracherkennungsprogramme nutzen, und wozu dann der ganze Aufwand?
Bitte bleib also bei einfachen Menü-Schnittstellen wie diesen hier (Menü-Punkt 0 für csv kann jetzt sogar komplett wegfallen)
Code:0 Soundfile *.csv in Programm öffnen / laden \n // csv kann jetzt sogar komplett wegfallen !
1 Soundfile *.wav in Programm öffnen / laden \n
2 Soundfile *.wav öffnen / abspielen + Plot \n
3 Sound aufnehmen per Micro / SoundCard \n
4 akt. Sound (Array im RAM) abspielen + Plot \n
5 akt. Sound optimieren (noise/cut) \n
6 akt. Sound (im RAM) als *.wav File speichern unter... \n
7 akt. Sound an FFT + Plot \n
8 akt. Sound cross correlation mit 1 wav File \n
9 akt. Sound cross correlation mit allen *.wav Files (auto) \n
und nutze bitte diese API-Schnittstellen mit dieser Syntax, wie ich sie im Prinzip bereits vor vielen Seiten gepostet hatte, nicht wesentlich anders:
Code:a) record_sound(int32_t * array, int32_t length);
b) save_sound2wavFile(int32_t * array, FILE * fp, char * filename); // über Zenity PopUp Window
c) FILE * fp = open_wavFile(int32_t * array, char * filename); // über Zenity PopUp Window
d) play_soundArray(int32_t * array, int32_t length);
e) play_wavFile(char * filename); // über Zenity PopUp Window
sowie
f) plotArray(int32_t * array, int32_t length, int y0);
g) optimizeArray(int32_t * array, int32_t length);
h) array2FFT(int32_t * array, int32_t length, double * fx, double * fy, int32_t FFT_length);
i) cross_corr(int32_t * array, int32_t * pattern, int32_t length);
Diese Funktionen müssen genau so in der Sound-Lib und ggf. in einer weiteren Sound-Tools-Lib genau so zur Verfügung stehen.
Nur wenn wir diese gemeinsame Menü- und API-Basis haben, kann unsere Arbeit auch später auf andere Anwendungen (z.B echte Wort-Steuerung von mobilen Robotern mit automatischer lernfähiger Spracherkennung) portiert werden.
ps,
Wenn du das LXTerminal Window neben dem openVG Window positionieren und in der Größe anpassen willst, können wir diesen Befehl verwenden:
Code:// LXTerminal window: pos (x,y): 520,0, size: 320x320
system("wmctrl -r LXTerminal -e 0, 520,0, 320,320");
Also zum Mitschreiben. Dir wird die Variante mit ncurses zu kompliziert? Obwohl du mit ncourses eigentlich nichts zu tun hast und es in der Struktur in Main eigentlich sehr klar zu sehen ist was wie wo passiert? Ich meine, da sind die ganzen case Aufrufe. Diese rufen sehr einfach die Funktionen auf die für die Spracherkennung benötigt werden. Da ist nicht viel Schnick schnack drum rum und das kann man dann auch ziemlich einfach in jede andere Menüstruktur ganz nach Belieben einbauen. Das hat weder was mit Linux-Programmierung noch sonst etwas zu und da ncurses meines Wissens nach auch auf WIndows verfügbar ist wäre sogar eine Portierung kein wirkliches Problem, aber wie gesagt, wie am Ende das Menü aussieht, ob man es ganz minimalistisch über eine Eingabeaufforderung oder bis hin zu einem aufgeblasenen QT oder Windows Fenster haben will ändert nichts an den eigentlichen Funktionen.
Genau das hier ist das Einzige was für die Spracherkennung dann irgendwie relevant ist. Ich denke das sollte man in jede für sich bevorzugte Variante umstricken können. Denn wo nun menuRet seinen Wert her bekommt ist ja eigentlich völlig egal, ob es nun über Zenity, den Terminal oder irgendein Fenster geschieht.Code:switch(menuRet)
{
case 0:
datei.open(_datei, ios::in);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei >> waveBuffer[i];
}
datei.close();
_speicher = "Wave vorhanden";
_status = "gesichert";
}
else _fehler = "Datei konnte nicht geöffnet werden!";
break;
case 1:
audioCapture(waveBuffer, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
_speicher = "Wave vorhanden";
_status = "ungesichert";
_datei = "";
break;
case 2:
datei.open(_datei, ios::in);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei >> waveTemp[i];
}
datei.close();
_fehler = "Datei " + _datei + " wurde abgespielt!";
_datei = "";
playCaptured(waveTemp, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
}
else _fehler = "Datei konnte nicht geöffnet werden!";
break;
case 3:
playCaptured(waveBuffer, SHRT_MAX, "plughw:1,0", 1, 12000, 8);
break;
case 4:
optimieren(waveBuffer, SHRT_MAX);
_fehler = "Speicher optimiert!";
_speicher = "Wave optimiert";
_status = "ungesichert";
_datei = "";
break;
case 5:
plotArray(waveBuffer, SHRT_MAX, 0);
break;
case 6:
dateiEndung = ".hhw";
dateiName = _datei + dateiEndung;
datei.open(dateiName, ios::out);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei << waveBuffer[i] << endl;
}
datei.close();
_status = "gesichert";
}
else _fehler = "Die Datei konnte nicht geöffnet werden!";
break;
case -1:
return 1;
break;
case -2:
_fehler = "Der Speicher ist leer! Erst laden oder aufnehmen!";
break;
}
Du willst kein OpenCV benutzen, okay damit kann ich leben. Wäre eine (portable) Möglichkeit gewesen das etwas bequemer zu haben. Aber gut, muss ja nicht.
ich nutze ausschließlich das LXTerminal für printf() etc., mit angepasster Größe an definierter Position, und ich habe keinen Platz für 3 Fenster (openVG, LXTerminal und ncurses) - und warum ncurses, wenn es auch ohne geht und ich es sowieso sonst niemals nutze?
Befehle wie dieser hier
Code:case 0:
datei.open(_datei, ios::in);
if(datei)
{
for(i=0;i<SHRT_MAX;++i)
{
datei >> waveBuffer[i];
}
datei.close();
_speicher = "Wave vorhanden";
_status = "gesichert";
}
else _fehler = "Datei konnte nicht geöffnet werden!";
break;
müssen in eine eigene Funktions-Wrap hinein, und die müssen diese Strukturen haben:
a) record_sound(int32_t * array, int32_t length);
b) save_sound2wavFile(int32_t * array, FILE * fp, char * filename); // über Zenity popen PopUp Window
c) FILE * fp = open_wavFile(int32_t * array, char * filename); // über Zenity popen PopUp Window
d) play_soundArray(int32_t * array, int32_t length);
e) play_wavFile(char * filename); // über Zenity popen PopUp Window
keine C++ Parameter, damit kann ich nicht arbeiten!
Ich bin ANSI C Programmierer, ich kann kein C++ selber benutzen für meine eigenen Zwecke.
Fehlerbehandlungen gehören in die Funktion mit hinein, nicht in das Menü!
Zenity fängt aber die File_IO fehler sowieso selber ab (man kann ja nur auswählen, was auch angezeigt wird)!
Und bitte immer nur 3 Leerzeichen für jede Einrückung, keine halbe Zeilenlänge!
Wir haben offensichtlich sehr unterschiedliche Auffassungen...
zumal ncurses im Terminal läuft und kein eigenes Fenster hat.
ja, naja, ich bin halt absoluter Programmieranfänger auf Arduino Sketch Level, brauche aber ntl alle Funktionen auch für meine eigenen Zwecke und Anwendungen.
Warum habe ich denn schon soweit es möglich war alles auf int32_t usw. umgestellt? Das ist auch mit ein Grund warum ich überhaupt angefangen habe ein Menu da rein zu stricken und ich versuche auch so gut es geht da Funktionen ein zu bauen die ein späteres Verwenden in den eigentlichen Anwendungsgebieten auch vereinfacht.
Zumal das was ich gepostet habe da aus meinem Code ist nicht das Menü, sondern nur was die eizelnen Aufrufe vom Menü letzten Endes machen. Das Menü selbst ist da gar nicht zu sehen. Wie gesagt, ist alles so angelegt das man es theoretisch mit sehr geringem Aufwand mit jeder Form der Auswahl betreiben kann.
hatte ich schonmal erwähnt dass ihr euren Code z.B. auf Github hochladen, forken und bearbeiten bzw. synchronisieren und kommentieren könnt? Ich will nicht dass ihr eure Entwicklung dahin beschränkt oder sowas, ich hab nur das Gefühl, dass es euch wesentlich helfen könnte einfach mit der gleichen Code basis zu arbeiten und darauf dann jeweils eine eigene Menüstruktur aufzubauen :D
Ihr ladet einfach den Kern des Programms hoch, schön gepackt und unterteilt in Methoden und Prozeduren und dann kann jeder in seinem eigenen Fork davon das Menü implementieren wie er es wünscht :D
Sonst gibts irgendwann nur noch streit und die Trennung von Kern und GUI tut dem Programmierstil gut und es kann alles dokumentiert werden und wenn was schiefgeht einfach ein rollback machen
wie Github aussieht, weiß ich, aber wie man damit arbeitet: kein Plan, und da will ich mich auch gar nicht erst einarbeiten müssen.
wesentlich sind im Moment nur die API-Tool-Funktionen samt Menü.
Was das Menü angeht, heißt das für mich:
ohne ncurses,
und was die API wave-Tools angeht, eben einfach so etwas ähnliches, in ANSI C (unter Zuhilfenahme von Zenity und popen(), wie ich es ja auch schon gepostet habe):
a) record_sound(int32_t * array, int32_t length);
b) save_sound2wavFile(int32_t * array, FILE * fp, char * filename); // über Zenity popen() PopUp Window
c) FILE * fp = open_wavFile(int32_t * array, char * filename); // über Zenity popen() PopUp Window
d) play_soundArray(int32_t * array, int32_t length);
e) play_wavFile(char * filename); // über Zenity popen() PopUp Window
sowie
f) plotArray(int32_t * array, int32_t length, int y0);
g) optimizeArray(int32_t * array, int32_t length);
h) array2FFT(int32_t * array, int32_t length, double * fx, double * fy, int32_t FFT_length);
i) cross_corr(int32_t * array, int32_t * pattern, int32_t length);
wenn wir uns auf diese Schnittstellen einigen können, ist doch alles prima, damit könnte ich anfangen zu arbeiten.
Mein Problem ist folgendes.
Wie du so schön sagst, du brauchst es so und so und so. Das ich in dem Programm hier aber schon massiv von meinem eigenen Programmierstil abgewichen bin ist dir klar oder? Ich habe noch nir int32_t verwendet zum Beispiel. Ich hätte nie angefangen ein Wav File zu dekodieren. Du sagst es ja, du brauchst es so und so um in deinen Projekten damit arbeiten zu können. Ich will jetzt nicht den Egoisten raus hängen lassen, aber schonmal auf den Gedanken gekommen das ich in meinen Projekten dann wieder umstricken muss?
Ist das dann geeinigt oder von deiner Seite durchgesetzt?Zitat:
wenn wir uns auf diese Schnittstellen einigen können
Ich frage deshalb weil:
Du willst da also eine Funktion, die von sich aus dann Zenity verwendet. Das heisst, will ich es später mal in meinem Projekt damit arbeiten muss ich den ganzen Zenity-Kram erst raus werfen. In meiner Variante wird per Menu einfach die Datei ausgewählt und dann an die Funktion übergeben. Das heisst, will ich es später mal in einem anderen Programm verwenden, eins was keine direkte Benutzerschnittstelle hat, kann ich die in dem Programm verwendete Methode zur Auswahl der Datei verwenden und die Funktion dann ungeändert einfach übernehmen, sprich einfach diasound.hpp einbinden und die Funktion benutzen. Nehmen wir mal an ich würde diese Funktion dafür benutzen wollen, eine Reihe von Dateien, welche spezifische Worte enthalten nach einander abzuspielen. Sagen wir ich habe einen Satz "Hallo Welt" den ich mittels vorgefertigten Wort-Dateien dann ausgeben möchte. Dann würde ich normalerweise ein vector mit den Dateinamen generieren und diese in einer Schleife abrufen. Das würde nicht funktionieren da ja Zenity aufgehen würde, was ich allerdings gar nicht sehen würde, wenn zB kein Monitor angeschlossen ist.Zitat:
e) play_wavFile(char * filename); // über Zenity popen() PopUp Window
"Einigen" wir uns auf dein Modell heisst das genau genommen, es funktioniert so das du damit arbeiten kannst in deinen Projekten während ich in meinen erst Aufwand betreiben muss um die erarbeiteten Funktionen zu verwenden. Das würde ich jetzt nicht als Win-Win ansehen.
@ceos
HaWe hat schon die Antwort geliefert, warum ich damit noch nicht gekommen bin ^^Zitat:
hatte ich schonmal erwähnt dass ihr euren Code z.B. auf Github hochladen...
Vielleicht kann dir ja wer anderes helfen auf der Basis von C++ und ncurses, ich muss da leider passen.
Und ich kann ja auch nicht garantieren, dass es dann später mit ANSI C und Zenity klappt.
Wir können es ja ganz schlau machen. Da ich die Funktionen ja sowieso so aufbaue, dass sie auch in anderen Programmen genutzt werden können machen wir es doch ganz einfach. Wir deklarieren eine globale Variable. Steht die auf 0 wird mein Menü gestertet, bei 1 deins. Wenn das okay für dich ist kann ich dir zeigen wie ich das meine.
Hallo,
soweit ich das verstanden habe, sollte man ncurses ODER die Standardausgaben nutzen. Das würde dann bald doppelten Code bei den Ausgaben bedeuten, es sei denn, Du kannst da per DEFINE was tricksen.
Zenity geht nur mit einem Fenstermanager. Soll es eine reine 'Konsolen-Anwendung' werden, dann muss eine Alternative her.
Ihr könntet auch gemeinsam genutzten Code in eine INCLUDE auslagern und die Oberfläche jeder für sich bauen.
Ein WAV-Export / -Import hätte den Vorteil, dass man die Dateien schnell mal auf 'Profisoftware' durch ein paar Filter jagen kann. Hinterher könnte man vor Filter mit nach Filter im neuen Format vergleichen / analysieren, um da was nachzubauen. Spracherkennung ist nicht ganz ohne, vor Allem, wenn unterschiedliche Sprecher erkannt und unter schwierigen Bedingen zuverlässig erkannt werden soll. Das schafft, wie bereits erwähnt, nicht mal Google in der Cloud zuverlässig. Euer Vorteil ist, dass es ein begrenzter Wortschatz ist.
Das sind alles nur Ideen. Ich selbst benötige ein solches Programm nicht. Verfolge jedoch Euren Fortschritt.
So war es gemeint mit der Include. Ich nutze meine, HaWe seine. Bzw. damit man nicht zu viel im Code ändern muss einfach eine Variable ändern so das das Programm weiss welche Variante genutzt wird und auch nur dessen Output dann angezeigt wird. Ist keine schwere Aufgabe.
Und ja Zenity will meines Wissens nach GTK. zumindest basiert meines Wissens nach LXDE auch zum Teil darauf. ncurse hingegen läuft ganz ohne X.
Und noch ist der Wortschatz begrenzt. Zumindest auf meiner Seite darf das auf Dauer durchaus mehr werden. Wenn es richtig gut läuft können es dann auch ganze Sätze werden. Dann ist eine 100%ige Übereinstimmung der Wörter auch nicht mehr ganz so wichtig, da das Programm dann mehr oder minder "versteht", dass das was da angekommen ist nicht wirklich sinnvoll ist und prüft was da eher Sinn machen würde. Funktioniert im Terminal eigentlich schon ganz gut. Da kann man auch Wörter nicht ganz richtig schreiben, Buchstaben verdrehen usw. Aber Eins nach dem Anderen. Im aller Schlimmsten Fall (wenn der Raspi das von der Leistung her nicht schaffen sollte) dann wird da eben doch mit Google gearbeitet werden müssen. Fände ich schade, aber man ist ja flexibel.
hallo,
von Anfang an doppelten Code halte ich für übertrieben - aber: OK, machbar.
Wesentlich sind für mich (auf die Gefahr, dass ich mich zum zig-sten Male wiederhole):
keine C++ Objekte, streams, Vectoren, strings
keine Installation von ncurses
reiner ANSI C Code
API Funktionen (ziemlich genau so, ggf. die Parameter ein wenig anders gesetzt):
a) record_sound(int32_t * array, int32_t length);
b) save_sound2wavFile(int32_t * array, FILE * fp, char * filename); // über Zenity popen() PopUp Window
c) FILE * fp = open_wavFile(int32_t * array, char * filename); // über Zenity popen() PopUp Window
d) play_soundArray(int32_t * array, int32_t length);
e) play_wavFile(char * filename); // über Zenity popen() PopUp Window
sowie
f) plotArray(int32_t * array, int32_t length, int y0);
g) optimizeArray(int32_t * array, int32_t length);
Menü im normalen LXTerminal, das genau diese (!) API Funktionen aufruft,
unter Zuhilfenahme von PopUpWindows für OpenFileDialog/SaveFileDialog/popen()+Zenity etc.
Dateiformat für sound: *.wav zum Speichern und Laden
Deine Erwartungen bezüglich der Leistungsfähigkeit muss ich allerdings etwas dämpfen:
Spracherkennung von Sätzen wird niemals funktionieren,
von gesprochenen Wörtern wird grundsätzlich immer nur das nach FFT-CC am besten passendste Muster ausgewählt (egal wie weit man daneben liegt),
keine Künstliche Intelligenz,
keine Lernfähigkeit wie beim Neuronalen Netz,
ausschließlich Trainierbarkeit der Erkennungsfähigkeit / Selektivität / Spezifität durch möglichst gute Frequenzfilter.
Es wird so ähnlich sein wie in dem bereits von mir verlinkten Video auf der Basis von Lego Mindstorms NXT, NXC Code, nur dass man wschl weniger schreien muss und es etwas schneller geht.
Dafür würde ich jetzt nicht zuviel bereits im Vorfeld in verschiedene Menüs investieren.
Das Menü kannst du selber bauen oder?
Denkst du mit der Methode wäre es Möglich unterschiedliche Stimmen identifizieren zu können?
wenn alle API Funktionen genau so existieren, wie oben beschrieben (inkl. popen()/Zenity), dann ist das Menü kein Problem
was die Worterkennung leisten wird, weiß ich nicht, FFT-CC ist Neuland für mich.
Warum willst du Zenity da unbedingt rein stricken?
weil OpenFileDialog und SaveFileDialog-Funktionen nunmal PopUpWindows mit File Browsern zur Auswahl benötigen, ist doch klar, das war doch der Sinn der Sache!
die Funktion kann ja durchaus doppelt gewrapt sein:
innen fopen()
und außen rum popen()
wie genau, ist egal, Hauptsache, am Ende steht ein FILE * fp, dessen Name man per Menü ausgewählt hat, entweder zum Öffnen oder zum Speichern.
Dann wäre aber eine extra Funktion für Zenity logischer die dann einen Dateinamen zurück gibt die man dann an die entsprechende Funktion weiter gibt. So wie mein Menü das auch macht. Da liesse ich mit mir reden.
Ich lass mich überraschen,
aber ein FILE * fp wird in jedem Fall gebraucht, da ja stdio.h Funktionen über den File Pointer (handle) funktonieren (u.a. close(FILE * fp) )
popen() hat ja praktischerweise fast dieselbe Syntax wie fopen(), wie schon woanders angemerkt.
Über das Öffnen und Schliessen brauchst du dir keine Gedanken zu machen. Das läuft dann in der Funktion selbst.
@hirnfrei es gibt Libs die tauschen FPs aus und Libs die tauschen Pfadnamen aus, bau einfach eine Variante mit ein, die es erlaubt FPs zu übergeben :D das macht das Leben einfacher, auch wenn man dafür einen klacks mehr code schreiben muss
mach einfach eine methode saveToFile(*FP), eine methode saveToFile(*Str) und eine methode *FP getFPfromStr(*Str)
in der saveToFile(*Str) dann einfach saveToFile(getFPfromStr(*Str));
sorry für die Pseudo Code verwendung, aber im Moment knabber ich heir an einem völlig unlogisch erscheinenden Ablaufproblem und hab keinen Cache für C-Code mehr im Hirn Frei
Wie rufst du zenity eigentlich von c aus auf?
auch im Original-Code dürfen ja nur FILE * fp vorhanden sein und keine streams oder Objekte oder was auch immer als files, von daher werden Dateinamen ja eh nur zur Auswahl benötigt
fp = fopen (char * filename, "r")
fp = fopen (char * filename, "w")
- und die Namen werden ja nun von Zenity gepiped.
wie Zenity funktioniert, steht schon weiter oben!
...gehe zurück auf Seite 19!
https://www.roboternetz.de/community...l=1#post628328
https://www.roboternetz.de/community...l=1#post628316
Anm.:
sowas wäre also NICHT erlaubt:
datei.open(_datei, ios::in)
der Code muss ja mit gcc compilierbar sein, daher nur ANSI C, kein C++!
Nicht das du denkst ich hätte dich verlassen ;).
Ich kämpfe mit Wave :(. Laden und direkt abspielen ist einfach. Das aber in einem Array zu haben mit dem man dann auch noch arbeiten kann ist schwer :(.
Ich werfe glaube ich auch gleich was an die Wand oder so. Laden ist kein Problem aber dann ist nur in einem Viertel des Arrays überhaupt etwas Anderes wie 0 und man kann sich das ganze Array auch nicht ansehen denn dann gibt es einen Seg-Fault. Wie mich das nervt!
- - - Aktualisiert - - -
Das ist das was ich in einer vorherigen Antwort meinte. Damit es für dich passt muss ich meine eigene Art zu Programmieren, so wie ich es gewohnt bin und wie es mit schnell von der Hand geht in grossen Teilen aufgeben.Zitat:
sowas wäre also NICHT erlaubt:
datei.open(_datei, ios::in)
Was ein Scheiss! Ich bin zu doof die Daten aus dem Wave richtig in ein Array zu bekommen das ich später verarbeiten und anschliessend ausgeben kann! Hat wer rat?
@HaWe, reicht es wenn das Programm mit den selbst erstellten Wav's arbeiten kann?