-
jap, denke ich auch ^^
übrigens:
ich hätte kein Problem mit einer globalen Variablen "soundCard", denn wenn man später alles in eine gesonderte Wrapper-lib verpackt (was mir ja eh am liebsten wäre)
<alsabrain.h> // brain ... hirn...du verstehst... ;)
dann könnte man ja super drauf zugreifen, und sehen muss man sie auch nicht im eigentlichen Programm.
Der ganze alsa-overhead wäre dann raus aus dem eigentlichen Anwendungs-Programm.
-
Sooooooo.
Das mit der globalen Variable habe ich nicht weg bekommen. Bleibt also erst einmal so. Aber jetzt schön in einer Header-Datei verwurstet. Hier ist der Code:
Code:
#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(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: Ü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 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;
}
Jetzt kannst du mit
Code:
playwave(Dateiname, Soundkarte);
zB:
playwave("/home/pi/Music/cantalow.wav", "plughw:1,0");
Ganz locker eine Wave abspielen.
-
sieht ja wirklich perfekt aus! 8-)
super, danke für deine Mühe :D
-
War keine wirkliche Mühe. Ich werde es sicher auch noch gebrauchen können ^^.
-
ich glaube ich werde dann auch mal in die Mikrophonsache mit einsteigen...
was für eine USB soundCard hast du (Hersteller- oder Bestell-Link) ?
-
Dieses da
Knappe 11€ und läuft ganz gut muss ich sagen. Vor Allem, einstecken und geht. Also nichts noch installieren oder umstellen oder wie auch immer. Das hat mir ganz gut gefallen. Bei Gentoo-Linux, was ich ja normalerweise nutze, muss man in der Regel für jede Hardware neue Module gebaut werden. Hat natürlich den Vorteil, der Kernel ist nur so gross wie er sein muss und es werden keine Treiber geladen die man nicht will.
-
satte 111 Euronen?? O.o
da kriegt man ja 3 Raspis für....
hättest aber du mal den Link zum Artikel bitte?
ich glaube, ich werde mir das hier mal näher angucken...
http://www.ebay.de/itm/External-USB-...UAAOxylh1SKKwm
ps,
allerdings ist es für später ja blöd, wenn man dem Pi immer hinterher brüllen muss zur Sprach-Fernsteuerung.
Da wäre dann ein mobiles (kabelloses) Micro-Sendegerät sicher sinnvoller, und ein Funkempfänger am Raspi selber, oder was denkst du?
(meine jetzige Fernsteuer-Konsole hat einen Arduino Due, der immerhin schon mal 2 DAC ports plus BT mit UART bei 115200 baud hat, was immer man dann später damit anfangen will, außer Joystick- und Keypad-Fernsteuerung...)
-
Da habe ich eine 1 zu viel getippt. Sorry.
Deine Variante ist aber auch nicht schlecht! Bei meinem blockiert das Teil die anderen USB-Ports. Kann man zwar mit einer Verlängerung umgehen, aber blöd ist es schon etwas.
Und die Idee mit einem Headset hatte ich auch schon. Aber meine Kinder hören leider auch nicht wenn ich nicht schreie ;). Also das wird schon funktionieren denke, hoffe ich.
-
haha, und du meinst, weil deine Kinder nicht auf Schreien hören (meine auch noch nie), da machts dann nichts, wenn der Pi dann auch nicht hört? :D
wie würde das denn technisch funktionieren mit einem Headset? Per BT? Da hast du mit deinem Pi 3 ja einen Vorteil, ich brauch da doch wieder einen USB Port.
Und dann wie weiter, wie kriegt man den Sound vom BT-Empfänger dann in den Pi als wav file?
-
Das weiss ich leider nicht. Habe ich bisher noch nicht mit gearbeitet. Ich hatte allerdings vor einigen Jahren ein BT Headset am Rechner, um mit meinen Leuten in SecondLife zu reden und wenn ich das richtig im Kopf habe lief das dann auch über Alsa, also das würde behandelt wie eine Netzwerkkarte und in dem Fall wäre es relativ einfach denke ich. Mal davon ausgehend das es mit dem Aufnehmen genau so einfach geht wie mit dem Abspielen bei Alsa.