PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Soundverarbeitung mit dem Raspi



hirnfrei
27.05.2016, 21:32
Mahlzeit!

So los geht es mit der Erkennung von akustischen Geräuschen und deren Auswertung. Dazu setze ich die USB-Soundkarte von Conrad (https://www.conrad.de/de/71-soundkarte-extern-usb-soundkarte-71-surround-externe-kopfhoereranschluesse-externe-lautstaerkenregelung-873877.html?sc.queryFromSuggest=true) ein, ein Mikro von meinem Headset, den Raspberry Pi 3 und mal für den Anfang tinyalsa.

Edit: Tinyalsa ist vom Tisch. Es mag gut sein, aber bei derart mangelhafter Dokumentation für mich nicht zu gebrauchen. Weiter mit Alsa!

Ich hänge mal ein Bild an wie das aktuell aussieht. Da ist dann auch noch der Arduino dabei, der regelt eigentlich die Stromquelle vom Raspi, da aber derzeit die Akkus wegen dem schönen Wetter anderweitig im Einsatz sind und ich auch noch nicht ganz fertig bin (Ende des Monats ist das Geld meist knapp) bleibt der Teil jetzt erst einmal weg.

Ziel 0 (Durch die Anregung von HaWe):

Initialisieren einer wav-Datei und abspielen mittels Alsa.

Abgeschlossen 30.05.2016

Ziel 1:

tinyalsa dazu bringen das das was das Mikrofon aufnimmt auch nutzbar in den Raspberry gelangt. (Wegen tinyalsa verworfen)

Mein Code dazu bringen, Sound über das Mikrofon aufzunehmen und wieder abspielen

Abgeschlossen 02.06.2016

Ziel 2:

Eingegangene Daten so aufbereiten, dass sie für eine Spracherkennung mittels PocketSphinx nutzbar sind.

HaWe
28.05.2016, 10:07
da bin ich ja mal echt gespannt. Bis jetzt konnte ich mit tinyalsa ja noch NICHTMAL

Ziel 0:
nen wav sound ABSPIELEN !!

(s. https://www.roboternetz.de/community/threads/69238-wav-Dateien-Programieren-von-Wiedergabe-und-Aufnahme)

hirnfrei
29.05.2016, 01:41
Ich habe mich jetzt noch nicht so intensiv mit tinyalsa beschäftigen können (irgendwie wollen Kinder immer Zeit für sich haben), aber dokumentiert ist das ja gar nicht gut!

peterfido
29.05.2016, 07:33
Hallo,

nein, in dem Paket steht auch etwas von Android. Da muss für das Raspi Debian wohl noch einiges angepasst werden. Da kann ich mehr schnellere Erfolge bei dem Code von aplay (und arecord) bei Eurem Vorhaben vorstellen. Das sollte sich als weiteren Thread gestartet auch relativ einfach so, wie es ist, steuern lassen. Von arecord aufgezeichnete Dateien müssen dann analysiert werden. Erstmal leise Geräusche rausfiltern, dann evtl. per mehreren Durchgängen das Aufgenommene entfeinern, bis sich ein Muster auch bei verschiedenen Aussprachen ergibt. Die Spitzen der verschiedenen Frequenzen lassen sich z.B. mittels FFT rausfinden. Das habe ich vor Jahren mal probiert, als ich für meinen Media-Player einen Sprectrum-Analyzer programmiert wollte. > Den habe ich dann einfach weggelassen ;) Heute habe ich mehr Erfahrung und würde es in einigen Tagen auch hinbekommen, brauche ich aber nicht mehr.

Ich selbst spiele mittels MPD Audi-Dateien ab. Der bietet auch einige Schnittstellen. Aufnehmen tue ich nicht. Spracherkennung ist auch nicht so einfach mal eben selbst programmiert. Da haben einige Firmen Jahre für gebraucht und auch heute noch schicken Siri, Amazon und Google die Sounds in die Cloud und bekommen Text zurück. Evtl. gibt es da eine API, die sich nutzen lässt. Das bedeutet dann ständiges online sein.

Falls Ihr etwas fernsteuern möchtet, schlage ich statt Spracherkennung eine App vor. Das bedeutet eine neue Programmierumgebung. Soll es für Android und Apple sein, zwei Programmierumgebungen. Oder einen Webserver auf dem Raspi und auf dem Smartphone / Tablet per Browser. Mittels Ajax lässt sich da schon was optisch ansprechendes erstellen.

HaWe
29.05.2016, 10:08
hallo,
aplay und arecord das sind ja externe Programme, d.h. die müssten per system Befehl innerhalb des C programms abgespielt werden, was dann auch die Portierbarkeit des Codes sehr einschränkt (z.b: Win10, falls es das mal für Raspi gibt oder auch für ganz andere Plattformen).
Schade, dass es keine originalen und frei portierbaren C/C++ API libs dafür gibt.
Aber was haben wir für eine Wahl, wenn nur aplay / arecord zur Verfügung steht... :-/



Ich würde persönlich dann auch nicht den 2. Schritt vor dem 1. tun und erstmal einen Player implementieren, der automatisch das Soundfile Format beliebiger wavs erkennt und dann abspielt.

Ich führe den Player-Gedanken mal weiter in dem Player-Thread....

https://www.roboternetz.de/community/threads/69238-wav-Dateien-Programieren-von-Wiedergabe-und-Aufnahme

peterfido
29.05.2016, 10:35
Hallo,

der Code von aplay ist frei verfügbar. Der Spracherkennung gebe ich nicht viel Erfolg. Eben gerade mit der Hotline der Telekom telefoniert. Der dämliche 'Automat', zu Beginn des Telefonates, versteht nicht mal ein 'Ja', welches bequem ausreichend laut per Freisprechfunktion mit leisem Radio im Hintergrund gesagt wurde. Dann habe ich eben mal mit Google 'gesprochen'. Was der da so teilweise versteht, ist echt abenteuerlich. Lustig ist die Antwort auf 'OK Google - Wer bin ich?'
31652

HaWe
29.05.2016, 10:57
Der Spracherkennung gebe ich nicht viel Erfolg.
ich sehe das auch als extremste Herausforderung, aber mit dem Umweg über eine FFT, bei der "unwichtige Spikes", die für bestimmte Frequenzbereiche stehen, gelöscht werden (habe ich schon mal gemacht), kann man schon einmal recht gut "ähnliche" Sounds vergleichen (z.B. Zelle für Zelle über einen Vergleich mit bekannten Mustern per minimaler Summe der Quadratischen Abweichungen).

Dennoch, erstmal müsste ein fertiger einfacher C Code existieren für Play und Record, die aplay man page ist mir da komplett unverständlich.

peterfido
29.05.2016, 14:40
Hallo,

naja ein Programm (z.B. aplay) ist recht einfach zu starten.

Welche Parameter Du da abfragen willst, weiß ich nicht. Am besten den Mixer vorher einmalig einstellen. Dann braucht man das nicht mit aplay machen.

Z.B. eine USB-Soundkarte als Standard setzen: Die Datei /etc/modprobe.d/alsa-base.conf edititieren. Der USB-Eintrag muss auf 0, alle anderen auf -2 stehen. Dann ist nach einem Neustart eine evtl. vorhandene USB-Soundkarte immer Standard für Mixer und aplay.

options snd-usb-audio index=0

Dann am besten in einem Autostart-Script (z.B. /etc/rc.local) den Mixer korrekt einstellen. Ich stelle die Lautstärke oft auf 80 Prozent, da hört man weniger Nebengeräusche. Sonst hört man evtl. durch den USB-Lautsprecher den Raspi arbeiten.


#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
# export WIRINGPI_GPIOMEM=1

amixer cset numid=3 1
amixer -c 0 cset numid=2 on,off
amixer set PCM 80%

exit 0



Dann halt aplay von einem C-Programm aus fernsteuern. Ich nutze im Beispiel als Eingabe eine USB-Multimediatastaur.


//Kompilieren: gcc -o /var/aptest/aptest /var/aptest/aptest.c -L/usr/local/lib -lpthread
//Aufrufen mittels: nice -1 /var/aptest/aptest < /dev/input/event0 &

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/sysinfo.h>
#include <time.h>
#include <linux/input.h>
#include <pthread.h>

int ziffer=0;
int beenden=2;
int zeit=0;
int shiftl=0;
int shiftr=0;
int strgl=0;
int strgr=0;
int capsl=0;
int apid=0;
FILE* aplaypipe; /* Filehandle fuer die Pipe */

void stopp()
{
char befehl[12] ="";
strcpy (befehl,"pkill aplay");
system(befehl);
}

void wiedergabe(char dateiname[])
{
char befehl[1024] ="";
strcpy (befehl,"nice -1 aplay /var/musik/");
strcat(befehl,dateiname);
strcat(befehl," &");
stopp();
aplaypipe=popen(befehl, "r");
printf("pipe: %d\n",aplaypipe);
pclose(aplaypipe);
}

void tastatur(void *name)
{
struct input_event event;
while ((read(0, &event, sizeof(event)) > 0) && (beenden==2) ) {
if (event.type != EV_KEY) continue;
// if (event.value != EV_KEY) continue; //Nur Tastendrücke erkennen, kein Loslassen. 0=losgelassen, 1=gedrückt, 2=Wiederholung(lang gedrückt)
printf("Typ: %d; Wert: %d; Code: %d\n",event.type,event.value,event.code);
if(event.value != EV_KEY){
switch (event.code) {
case 164:wiedergabe("girlfriend.wav");break;//Play
case 166:stopp();break;//Stop
case 62:stopp();beenden=0;break; //Close
}
}
}
beenden=0;
pthread_exit((void *) 0);
}

int main(int argc, char** argv)
{
pthread_t t1;
if(pthread_create(&t1, NULL, (void *)&tastatur, (void *)"Tastatur") != 0)
{
fprintf(stderr, "Fehler bei Tastatur......\n");
exit(0);
}

while (beenden > 0)
{ sleep(1);
zeit++;
if (zeit==30)
{
zeit=0;
printf("Wieder 30 Sekunden um.\n");
}
}
usleep(50);
printf("***********Ende************\n");
return 0;
}



Die WAV-Datei liegt bei mir unter /var/musik und heißt girlfriend.wav Die Rechte sollten auf 644 stehen.


Edit:
Der Code wurd auf das Wesentliche gekürzt und enthält evtl. noch ungenutzte Variablen und Verweise.

Edit2:
Evtl. Fehler werden nicht abgefangen. (Z.B. falsch geschriebener Dateiname, falsche Dateirechte, etc)

HaWe
29.05.2016, 15:25
ganz herzlichen Dank, das werde ich baldmöglichst mal austesten.
Es ist ja wirklich recht komplex, aber trotzdem noch sehr überschaubar.
Fehler braucht man auch nicht abfangen, es ist ja für ein "fixes" C-programm mit fest vorgegebenen wav-Files.

Aktuell ist mein raspi durch eine Pinverwechslung (GND gegen gpio.26 PWM) durchgeschmort.
Ersatz ist aber geordert.

OT:
Meine Lehre daraus:
ich werde die Breadboards mit T-Cobbler weitgehend schassen und mir ein paar Bauteile auf Raspi-Shields mit durchgeschleiftem GPIO-Header fest verlöten (lassen). Das mit den GNDs überall dazwischen ist ja wirklich dämlich lebensgefährlich konstruiert (für den Pi).
/OT

hirnfrei
29.05.2016, 16:58
Davor habe ich auch die ganze Zeit Schiss, dass ich da einen Pin wo dran klemme wo der Raspi es dann nicht verträgt. Daher meine Variante mit der Platine. Jede Strippe die an den Arduino geht ist beschriftet und wenn ich da was neues dran löte wird anschliessend erst getestet wie viel Spannung da wirklich drüber geht, bevor es dann mal wirklich an den Raspi gesteckt wird. Schiss hab ich dennoch immer und auch wenn ich nichts verändert habe, bevor ich den Arduino an mache gucke ich immer ob noch alle Kabel dort sind wo sie sein sollen.

Warum haben die beim Raspi nur 3,3V genommen?

HaWe
29.05.2016, 18:07
3,3V ist bei allen ARM Boards Standard, auch bei den ARM Arduinos, dem Teensy, BeagleBone Black+Blue, Pine64...
5V dagegen sind veraltet und stammen aus den AVR-Zeiten, viele Komponenten haben heute aber sogar bereits 1,8V Standard.
Aber auf den Arduinos liegt alles sauber getrennt, nur bei den Spannungs- und gpio-Pins geht beim Raspi alles durcheinander wie Kraut und Rüben. Als ob man nicht erst einen Block mit 4 GND, dann 2x 5V und dann 2x3,3V hätte machen können - und dann erst die gpios hintendran. Also nee...

Aber zurück zum Thema:
hast du schon wavs abspielen und aufnehmen können?

hirnfrei
29.05.2016, 18:19
Ah so ist das. Alles klar! Danke für die Info.

Nein. Aber immerhin kann ich die Soundkarte öffnen, initialisieren, die Parameter auslesen und das Ganze wieder schliessen. Es geht also voran ;)

peterfido
29.05.2016, 20:40
Hallo,

das ist der Trend. Kleinere Spannung=weniger strom=weniger Leistung. Nebenbei ist der Pegel schneller von GND auf 3V3 als auf 5V0. Die nächste Stufe ist dann 1V8. Die Ausgänge sind nur als Pegel zu verarbeiten. Maximal 3mA würde ich da fließen lassen.

Mein Beispiel da oben ist nicht optimiert und soll veranschaulichen, wie man aplay steuern kann. Evtl. muss das Nice weggelassen werden, damit in aplaypipe die pid von aplay abgelegt wird. Die bräuchte man, wenn man mehrere Sounds gleichzeitig / versetzt / wie auch immer laufen hat und nicht alle auf einmal stoppen möchte. Das ist in meinem Beispiel nicht drin.

Läuft immer nur ein Sound / WAV-Datei, dann kann man auch rein mit system arbeiten.

Ungestetes Beispiel:


void stopp()
{
system("pkill aplay");
}

void wiedergabe(char dateiname[])
{
char befehl[512] ="";
stopp();
strcpy (befehl,"nice -1 aplay /var/musik/");
strcat(befehl,dateiname);
strcat(befehl," &");
system(befehl);
}

HaWe
29.05.2016, 21:04
kann man nice -1 nicht sowieso einfach rauslassen?
prio == -20...+19, 0 ist ja standard, und -1 braucht auch noch root.

system ("aplay /var/musik/dateiname &");

:?:

hirnfrei
29.05.2016, 21:52
Also ich habe der Karte einen ziemlich fiesen Ton entlockt. Der Ton war so toll das ich ihn immer noch höre ^^.

Also wo stehe ich. Ich kann mittels ALSA die Soundkarte öffnen, die Parameter abrufen, sie beliebig setzen und vorbereiten.

An dieser Stelle käme dann das mit dem Sound. Da hatte ich den Fehler das ich nur einmal Daten gelesen habe und diese dann laufend zur Karte geschickt hatte. Lese ich das File komplett, oder auch stückweise gibt es gar keinen Ton von sich.

Letzten Endes wird die Soundkarte dann auch wieder deaktiviert.

Bliebe die Frage, wie bringe ich dem das mit den Audiodaten näher? Ich nehme an ich muss das Wav-File erst entsprechend verarbeiten. So mit Headern usw. Habe ich so aber noch nicht gemacht mit Audiodateien.

HaWe
30.05.2016, 11:47
Die Spracherkennung (vergleich von Audio-Signalen) läuft meist über eine FFT (Fast Fourier Transformation), Stichwort: audio cross correlation
http://dsp.stackexchange.com/questions/736/how-do-i-implement-cross-correlation-to-prove-two-audio-files-are-similar

Grundsätzlich kann man versuchen
a) den Micro-Sound in Real time zu verarbeiten (wschl.schwierig)
b) der einfachste Weg (und der einzige, den ich mir für tinyalsa vorstellen kann), wäre aber:


0. überprüfen, ob du beliebige wav files überhaupt mit tinyalsa abspielen kannst ,
ansonsten anderes Programm
1. Code zum Aufnehmen eines .wav Files schreiben (entweder auch tinyalsa oder anderes Programm),
und die Qualität vom Ergebnis testen (abspielen), ggf Aufnahmeparameter anpassen
2. a) erzeugte wav-File Daten in einen FFT-kompatiblen array passender Größe konvertieren,
dann einer FFT unterwerfen (Array aus komplexen Zahlen, also 2D Array),
b) dann die Transformierte weiter verarbeiten (s. mein Post oben) um Rauschen / Störfrequenzen etc. zu elimieren
c) debug: zur Kontrolle die FFT auf das veränderte Ergebnis anwenden,
und dann das Ergebnis wieder als wav abspeichern und abhören
d) goto 2.b)...
3. Anlage einer wav-Datenbank mit verschiedenen definierten Sound/Sprach-Records als Vergleichsbasis

die Parts mit dem Play- und dem Record-Programm wären also das erste, was du schreiben und testen musst.

hirnfrei
30.05.2016, 11:55
Tue ich doch. Als ich davon Sprach die Wav Dateien entsprechend zu verarbeiten war eigentlich gemeint, die Heder auslesen, Daraus die entsprechenden Werte für Alsa übernehemen, die Soundkarte entsprachend initialisieren, dann die Daten abspielen und Alles wieder schliessen.

Gestern Abend bin ich noch so weit gekommen, dass beim Abspielen ein kurzes Knacken zu hören ist. Kein Grund einen Luftsprung zu machen, aber immerhin ein weiterer Schritt. Hab mir gestern erst einmal angeschaut wie so ein Wav aufgebaut ist. Wie gesagt, hatte damit bislang noch nie etwas zu tun. Ich denke mal, ich übergebe da noch ein paar Parameter nicht richtig. Aber das sollte ich hin bekommen.

Erst danach kommt das mit dem Aufnehmen usw. Immer schön Schritt für Schritt!

HaWe
30.05.2016, 12:01
deine Aussage

Also wo stehe ich. Ich kann mittels ALSA die Soundkarte öffnen, die Parameter abrufen, sie beliebig setzen und vorbereiten.

An dieser Stelle käme dann das mit dem Sound. Da hatte ich den Fehler das ich nur einmal Daten gelesen habe und diese dann laufend zur Karte geschickt hatte. Lese ich das File komplett, oder auch stückweise gibt es gar keinen Ton von sich.

Letzten Endes wird die Soundkarte dann auch wieder deaktiviert.

Bliebe die Frage, wie bringe ich dem das mit den Audiodaten näher? Ich nehme an ich muss das Wav-File erst entsprechend verarbeiten.
klang nicht so, als ob du schon einwandfrei abspielen und aufnehmen könntest, und erst dann kommt ja die Weiterverarbeitung.

Wenn du aber schon play- und record-Code hast, dann poste ihn mal bitte!

hirnfrei
30.05.2016, 13:36
Entweder du verstehst mich, oder ich verstehe dich falsch ^^.

Was ich sagen wollte, die Soundkarte aktivieren konnte ich schon mittels C/C++ (und Geany ^^). Nur bekam ich die Soundkarte bisher nur dazu einen schmerzhaften Ton zu produzieren. Da ich bislang von Sound-Formaten komplett 0 Ahnung hatte musste ich erst einmal lernen wie ich die wav Datei so zerpflücke, dass ich die Soundkarte mit den entsprechenden Werten (Kanäle, Bit...) initialisieren und aus der Datei dann den abspielbaren Bereich heraus nehmen muss.

Und siehe da, Mission erfüllt ;).

Den Code bereite ich noch ein wenig auf. So gefällt mir das nicht und schön ist das auch nicht. Dann poste ich den. Der ist dann aber minimal, geht also auf keine Fehler oder so ein.

- - - Aktualisiert - - -

Hilfe!

Ich hab gerade voll die Blockade!

Aktuell setze ich die globale Variable


snd_pcm_t *soundKarte;

Ich mag globale Variablen aber eher weniger und wollte die nun in einer Funktion verwursten. Die Funktion sollte aufgerufen werden:


soundkarteIni("plugdev:1,0", soundKarte);

Nur wie zur Hölle muss ich die Funktion nochmal schreiben, dass *soundKarte von der Funktion gefüllt wird?

Ich kriege grade voll die Krise!

HaWe
30.05.2016, 13:43
ja, ich hatte dich falsch verstanden.
Jetzt aber doch wohl richtig.

und jetzt bin ich gespannt was wie bereits geht ... :cool:

Kannst du mit vllt auch mal deine Soundkarte genau verlinken? Wenn alles funktioniert mit play/record, hol ich mir die gleiche!

(oh, hat sich gerade überschnitten...)

hirnfrei
30.05.2016, 15:56
Das mit der globalen Variable gefällt mir zwar immer noch nicht aber ich bin aktuell zu doof um es anders zu regeln.

So funktioniert es auf jeden Fall!



#include <alsa/asoundlib.h>

#include <iostream>

#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(const char *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 == NULL)
{
err = snd_pcm_open(&soundKarte, "plughw:1,0", SND_PCM_STREAM_PLAYBACK, 0);
}
else
{
err = snd_pcm_open (&soundKarte, name, 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: Üarameters können nicht gesetzt werden(" << snd_strerror (err) << ")" << endl;

return false;
}
// snd_pcm_hw_params_get_buffer_size(hw_params, &bufferSize);

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 main()
{
FORMAT format;
FILE_head head;
CHUNK_head chead;

char *wave;

register snd_pcm_uframes_t count, frames;

int datei;

unsigned int WaveSize;

datei = open("/home/pi/Music/cantalow.wav", 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("plughw:1,0", 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;
}

HaWe
30.05.2016, 16:08
in welchem Ober-Verzeichnis liegt deine alsa/asoundlib.h ?
und wie lautet deine Compile/Build Parameter Liste?

und wo steht, was "soundKarte" ist ? Bzw. wie man das auf die eingebaute oder andere externe "Karten" umstellt?

peterfido
30.05.2016, 16:13
Hallo,


plughw:1,0
bedeutet, die zweite verfügbare Soundkarte. Demnach darf die modprobe nicht dahin geändert werden, dass USB-Sound die erste ist. Falls das geändert wurde, dann
plughw:0,0

hirnfrei
30.05.2016, 16:21
Dazu notwendig ist (falls noch nicht vorhanden)


sudo apt-get install libasound2-dev

sowie braucht es beim Linken noch


-lasoundlib

für g++.

- - - Aktualisiert - - -

Das übergibst du bei


Init("plughw:1,0", format.wChannels, format.dwSamplesPerSec, format.wBitsPerSample);

Wie Peter schon sagte, 1 ist die zweite verfügbare Soundkarte. Da Raspi eine drin hat ist diese 0. Welche Nummer die entsprechende Karte hat kannst du zum Beispiel mit


aplay -l

heraus finden.

HaWe
30.05.2016, 16:31
ok, ich hab heute abend wieder einen Pi (2).
Wie ist jetzt der genaue komplette g++ Build-Befehl (ich verwende ja Geany, das hat aber die gleichen wie der normale make Befehl) ?

Und in welchem Ober-Verzeichnis liegt deine alsa/asoundlib.h ?

hirnfrei
30.05.2016, 16:37
Ich verwende im Moment auch Geany. Nur mein eigentlicher Bot will cmake.

Kompilieren:

g++ -Wall -std=c++0x -pthread -lasound -c "%f"

Erstellen:

g++ -Wall -std=c++0x -pthread -lasound -o "%e" "%f"

HaWe
30.05.2016, 16:53
was ist c++0x und warum?
ich habe
-std=c++11

Und in welchem Ober-Verzeichnis liegt deine alsa/asoundlib.h ?

hirnfrei
30.05.2016, 17:14
c++0x stand schon in der Zeile. Da habe ich hier nichts dran geändert. c++11 geht natürlich auch!

Wenn du libasound2-dev installiert hast liegt es im Standardverzeichnis. Also ich musste da nichts ändern oder irgendwo rein kopieren.

HaWe
30.05.2016, 19:10
ich hatte mal was installiert aber woanders hin.
Daher muss ich wissen, wie dein Verzeichnis genau heißt und wo es liegt.

ps, hast du auch das installiert?

git clone https://github.com/tinyalsa/tinyalsa.git
cd tinyalsa
make

- - - Aktualisiert - - -

hmmmm
schriebst du nicht oben, du würdest tinyalsa benutzen - oder habe ich da was falsch gelesen?
sieht nämlich so aus, al ob du gar nicht tinyalsa benutzt, sondern das originale alsa .... kann das sein?

- - - Aktualisiert - - -

edit -

alles klar, es hat mit der tinyalsa-Lib nichts zu tun!
Dann ist es auch klar, dass das mit den lib-Pfaden nicht passte, das hat sich also erledigt.

Gute Nachricht:
Beispielprogramm lässt sich compilieren und läuft!

:cool:

hirnfrei
30.05.2016, 20:04
Recht hast du. Tinyalsa mag ja gut sein, aber ohne Dokumentation ist das einfach Müll. Klar kann man es aus dem Quelltext heraus suchen, aber das ist mühsam. Also habe ich es mal mit Alsa selbst versucht und siehe da, funktioniert. Zudem finden sich für Alsa selbst hier und da Tutorials bzw. Einträge in Foren. Jedes Problem das ich hatte hatte auch schon irgend wer vor mir und von daher bekam ich in der Regel auch die Antworten dazu.

Also weg mit Tinyalsa ;). Habe ich im ersten Post hier im Threat auch schon geändert.

HaWe
30.05.2016, 21:01
große Klasse, super hingekriegt!

meine Frage hierzu lagere ich aber mal hierhin aus, es hat ja nichts direkt mit deinem Projekt zu tun...

https://www.roboternetz.de/community/threads/69238-wav-Dateien-Programieren-von-Wiedergabe-und-Aufnahme?p=627605&viewfull=1#post627605

hirnfrei
31.05.2016, 20:51
Kann man im Text hier nichts durchstreichen?

HaWe
31.05.2016, 22:07
nö, ist mir hier nicht bekannt.

- - - Aktualisiert - - -

hab mir jetzt auch eine USB Soundkarte bestellt, dauert aber was, kommt vom freundlichen Chinesen ;)
wir können ja aber schon mal anfangen mit der Spracherkennung.

Da stellen sich mir die Fragen:
Können wir hier im Forum ohne große Einschränkungen wav files hochladen und auf diese Weise austauschen?
und dann: kriegst du auch per alsa ein wav-Aufnahme (record) hin?

hirnfrei
02.06.2016, 12:03
Als wav speichern sollte nicht das Thema sein. Dann muss eben noch Header und Chunk davor. Und tauschen, wenn nicht hier kann man das immer noch per Mail oder so machen. Wege gibt es da ja viele ;).

Spracherkennug gerne, aber dafür muss erst einmal die Aufnahme klar sein.

hirnfrei
29.06.2016, 12:05
So, da das mit dem selbst Bauen eine Spracherkennung wohl doch zu langwierig ist und ich mittlerweile PocketSphinx entdeckt habe schwenke ich jetzt in diese Richtung um. Bleibt immer noch lokal, aber mit funktionierender Spracherkennung.

Also Pocketsphinx funktioniert zumindest auf dem Pi. Da habe ich jetzt schon mehrere Beschreibungen gelesen, wenn auch unter Verwendung von Jasper. Aber der Einbau in ein eigenes Programm sieht auch nicht sonderlich schwer aus und die Daten der Soundkarte müssten dafür auch schon nutzbar sein. Mal sehen.

- - - Aktualisiert - - -

Yeah es geht voran!

Trainiert wird schon gut wie ich finde, deutsche Model Daten sind auch vorhanden und HALLO erkennt er schon ganz gut! Nur aus Frosch macht er PST oder PORSCHE. Ich habe das Gefühl das mein Mikro einfach zu viel rauscht. Nur liegt das jetzt am Mikro oder an meiner Art die Daten zu einzulesen?

hirnfrei
02.07.2016, 16:21
Ich versuche mich jetzt mit Marsya. Nach dem was ich gelesen habe sollte es möglich sein damit die Aufzeichnung so zu verändern, dass die für Pocketsphinx besser zu verarbeiten ist. Bin mal gespannt.

Zudem lese ich mich gerade in das Erstellen und Erweitern von Sprachdaten für Pocketsphinx ein. Es wird immer empfohlen Pocketsphinx in English zu benutzen, da dort die Sprache einfach besser unterstützt sei. Aber wenn man das so durch zieht wird das Deutsch ja auch nicht besser!

Ich versuche einen Weg zu finden das das Programm unbekannte Wörter selbstständig lernen kann. Mal schauen was so geht. Mein Bot soll schliesslich am Ende deutsch können und nicht englisch.