-
OT
mit einem Apple User würde ich mich blendend verstehen, was intuitive Benutzung angeht (auch wenn inzwischen Unix druntersteckt) - Steve Jobs hatte da genau die richtige Idee (und wurde erfolgreich von Gates kopiert). So gesehen ist Apple gar nicht so weit von Windows entfernt. Ich verabscheue allerdings Apples Beutelschneiderei und ihre "high walls and holy gardens".
Was allerdings Roboter-Programmierung angeht, liegt für mich Arduino meilenweit vorn.
Das eine ist halt das OS (von dem man gar nichts merken sollte),
und das andere ist die C-Programmierumgebung, mit der man einfach und (ebenfalls) intuitiv arbeiten können muss.
/OT
Bin sehr gespannt, wie die wav Daten aufbereitet werden können. Für die FFT muss man sie ja in einen Array mit einer bestimmten Dimension zwängen, und da denke ich: je kleiner die Bit-Rate und Sample-Frequenz, desto schneller und besser insgesamt - 8bit und 11kHz müssten dicke reichen, oder?
-
Das weiss ich eben noch nicht. Hab so gesehen noch nie ein Wav in roher Form gesehen. In meinem Programm ist es ja ein char, aber um es abzuspielen muss man jedes einzelne char einzeln übergeben. Genau genommen ist es also ein dickes int array. Jetzt muss ich eben mal schauen wie das so aussieht. vielleicht in eine csv Datei speichern und mal durch LibreOffice plotten lassen, ob da dann schon das eigentliche Audiomuster heraus kommt. Das wäre dann ja einfach ;). Auch denke ich, wenn speichern wird es ja eigentlich nicht unbedingt ein bekanntes format sein müssen. Es sei denn man will es auch mit einem normalen Player abspielen. Rohdaten sollten da eigentlich reichen, dann muss man nicht noch Header erzeugen und auslesen.
-
normalerweise wird ja mit 44kHz in 16 bit gesampelt.
Der Header muss dann raus.
d.h. du hast in 1 sek 44000 int16_t
das muss per 11kHz auf rund 11 000 Werte runter,
die FFT rechnet aber mit floats (da wäre es sogar egal, ob 16 oder 8 Bit Auflösung)
Geben wir dem gesprochenen Wort 2-3 sec, wären es dann 22000-33000 float-Zellen.
Zur cross correlation muss man mindestens noch mal die gleiche Länge Nullwerte hinten dran hängen,
und die FFT rechnet dabei mit Komplexen Zahlen (2 float arrays).
da wäre also eine insgesamte Arraygröße von
float fx_[fxyLen], fy_[fxyLen]
mit
#define fxyLen USHRT_MAX // == 2^16
passend.
Damit hätte man was für den Anfang...
ps,
hier ist mal ein FFT Programm, das ich für den Lego NXT geschrieben habe.
War damals aber zu langsam für cross correlation auf dem Bytecode-Interpreter.
Anfangs war es komplettes Neuland für mich als Lego-Programmierer, aber mit der Zeit habe ich ein wenig "Gefühl" für die Sache entwickelt.
Ist schon sehr beeindruckend, was die FFT leistet.
http://www.mindstormsforum.de/viewto...p=56262#p56262
-
Also es funktioniert schon zum Teil. Ich kann aufnehmen, die Bitrate und Frequenz einstellen und es wieder abspielen. Aber das rauscht abartig!
-
könntest du mal bitte deinen Aufnehme-Code posten?
Und dabei v.a. auch, wo und wie du die Parameter für Empfindlichkeit / Aufnahmelautstärke etc. justierst?
Ist das Rauschen konstantes "weißes Rauschen" (so wie konstant lautes Meeresrauschen) oder "bunt" oder sogar von wechselnder Art oder Lautstärke (so wie wenn durch Hintergrundgeräusche wie Autos, Stimmen, Motore, Küchengeräusche oder Radio "verrauscht") ?
-
Hier die Erweiterung meiner Header-Datei, die ich dir ja schon geschickt habe.
Code:
#include <alsa/asoundlib.h>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.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)
{
cout << "Init: Kann die Soundkarte nicht öffnen! " << name << " (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
cout << "Init: Parameter können nicht initialisiert werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
{
cout << "Init: Parameter können nicht ermittelt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
err = snd_pcm_hw_params_set_rate_resample(soundKarte, hw_params, resample);
if(err < 0)
{
cout << "Init: Resampling kann nicht eingeschaltet werden " << snd_strerror(err) << endl;
return err;
}
if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
cout << "Init: Zugriffstyp kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
{
cout << "Init: Sample-Format kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
{
cout << "Init: Anzahl der Kanäle kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
{
cout << "Init: Sample-Rate kann nicht auf " << actualRate << " gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
{
cout << "Init: Parameters können nicht gesetzt werden(" << snd_strerror (err) << ")" << endl;
return false;
}
snd_pcm_hw_params_free(hw_params);
if((err = snd_pcm_prepare(soundKarte)) < 0)
{
cout << "Init: Audio kann nicht zur Nutzung vorbereitet werden (" << snd_strerror (err) << ")" << endl;
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)
{
cout << "Init: Kann die Soundkarte nicht öffnen! " << name << " (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
cout << "Init: Parameter können nicht initialisiert werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_any(soundKarte, hw_params)) < 0)
{
cout << "Init: Parameter können nicht ermittelt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_access(soundKarte, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
cout << "Init: Zugriffstyp kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_format(soundKarte, hw_params, bits)) < 0)
{
cout << "Init: Sample-Format kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_channels(soundKarte, hw_params, channels)) < 0)
{
cout << "Init: Anzahl der Kanäle kann nicht gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params_set_rate_near(soundKarte, hw_params, &actualRate, 0)) < 0)
{
cout << "Init: Sample-Rate kann nicht auf " << actualRate << " gesetzt werden (" << snd_strerror (err) << ")" << endl;
return false;
}
if((err = snd_pcm_hw_params(soundKarte, hw_params)) < 0)
{
cout << "Init: Parameters können nicht gesetzt werden(" << snd_strerror (err) << ")" << endl;
return false;
}
snd_pcm_hw_params_free(hw_params);
if((err = snd_pcm_prepare(soundKarte)) < 0)
{
cout << "Init: Audio kann nicht zur Nutzung vorbereitet werden (" << snd_strerror (err) << ")" << endl;
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;
}
vector<int> audioCapture(int sek, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
int err, zielzeit;
char *puffer;
vector<int> input;
time_t t;
t = time(NULL);
zielzeit = t + sek;
puffer = (char *) malloc(1);
cout << "Beginne Aufnahme von " << sek << " Sekunden!" << endl;
if(InitCapture(name, channels, actualRate, WaveBits))
{
while(t < zielzeit)
{
err = snd_pcm_readi(soundKarte, puffer, 1);
input.push_back(puffer[0]);
t = time(NULL);
}
UnInit();
}
else cout << "Bei der Initialisierung ist ein Fehler aufgetreten!" << endl;
cout << "Aufnahme beendet!" << endl;
return input;
}
void playCaptured(string wave, string name, unsigned int channels, unsigned int actualRate, unsigned short WaveBits)
{
register snd_pcm_uframes_t count, frames;
unsigned int WaveSize = wave.length();
Init(name, channels, actualRate, WaveBits);
count = 0;
// cout << "Hier" << endl;
do
{
frames = snd_pcm_writei(soundKarte, wave.c_str() + 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);
UnInit();
}
und hier meine main.cpp
Code:
#include <iostream>
#include <vector>
#include <stdio.h>
#include "diaSound.hpp"
int main()
{
vector<int> input;
string wave;
input = audioCapture(5, "plughw:1,0", 1, 44100, 16);
for(int i=0;i<input.size();i++) wave += input[i];
playCaptured(wave, "plughw:1,0", 1, 44100, 16);
return 1;
}
Es hört sich an als wäre das Mikro massiv übersteuert.
-
was ist der Unterschied zwischen playWave und playCaptured ?
könnte man das ggf vereinheitlichen?
-
bei playWave(); übergibst du ein Dateiname. Dieser wird geladen, die Header und Chunk ausgelesen, damit die Soundkarte geöffnet und das dann abgespielt.
Bei playCaptured(); übergibst du nur die Rohdaten und gibst die Daten für die Soundkarte vor.
Vereinheitlichen dürfte schwierig werden, da man dann für playWave ebenfalls die Vorgaben für die Soundlarten treffen müsste, auch wenn diese dann von der Datei überschrieben werden.
-
achso, playCaptured spielt einen array ab, keinen File, richtig?
vlt wäre dann
playSoundarray
besser, denn nicht alles ist ja "gecaptured"... 8-)
aber was ist denn
string wave
?
wieso string?
-
Das kommt aus der Funktion snd_pcm_writei();. Die erwartet ein char *. Warum auch immer.