So mein Freund. Mein Spieltrieb ist durchaus entzückt. Hier das Ergebnis:
main.cpp
Code:
#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;
}
diasound.hpp
Code:
#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();
}
menu.hpp
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);
}
}
Da gibts doch jetzt nichts mehr zu meckern . Jetzt gehts dann ans optimieren usw.
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.
Lesezeichen