Über das Öffnen und Schliessen brauchst du dir keine Gedanken zu machen. Das läuft dann in der Funktion selbst.
Ü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 übergebendas 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
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
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.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?
Der thread ist zwar schon ein bischen älter, aber ich habe den WAV Player mal ein bischen in Ordnung gebracht:
#include <alsa/asoundlib.h>
#include <bitset>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
/**
* The canonical WAVE format starts with the RIFF header
*/
typedef struct
{
// Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
// The default byte ordering assumed for WAVE data files is little-endian.
// Files written using the big-endian byte ordering scheme have the identifier RIFX instead of RIFF.
unsigned char id[4];
/*
36 + SubChunk2Size, or more precisely:
4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
This is the size of the rest of the chunk
following this number. This is the size of the
entire file in bytes minus 8 bytes for the
two fields not included in this count:
ChunkID and ChunkSize.
*/
uint32_t length;
// Contains the letters "WAVE" (0x57415645 big-endian form).
unsigned char type[4];
} Header;
/**
* The "WAVE" format consists of two subchunks: "fmt " and "data":
* The "fmt " subchunk describes the sound data's format
*/
typedef struct
{
// Contains the letters "fmt " (0x666d7420 big-endian form).
unsigned char id[4];
// 16 for PCM
uint32_t length;
// PCM = 1 (i.e. Linear quantization)
// Values other than 1 indicate some
// form of compression.
uint16_t fmt;
// Mono = 1, Stereo = 2, etc.
uint16_t channels;
// 8000, 44100, etc.
uint32_t samplesPerSec;
// ByteRate == SampleRate * NumChannels * BitsPerSample/8
uint32_t avgBytesPerSec;
// BlockAlign == NumChannels * BitsPerSample/8
// The number of bytes for one sample including all channels.
// I wonder what happens when this number isn't an integer?
uint16_t blockAlign;
// 8 bits = 8, 16 bits = 16, etc.
uint16_t bitsPerSample;
} Format;
#define WAVE_FORMAT_IEEE_FLOAT 3
/**
* The "data" subchunk contains the size of the data and the actual sound
*/
typedef struct
{
// Contains the letters "data" (0x64617461 big-endian form).
unsigned char id[4];
// Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8
// This is the number of bytes in the data.
// You can also think of this as the size
// of the read of the subchunk following this number.
uint32_t length;
} ChunkHead;
class WavePlayer
{
private:
snd_pcm_t* mAudioDevice;
uint32_t mDataSize;
char* mData;
uint16_t mChannels;
uint32_t mSampleRate;
uint16_t mBitsPerSample;
uint32_t mFrameCount;
string mAudioDeviceName;
string mWaveFileName;
bool openDevice ();
bool setHwParams (uint32_t channels, uint32_t sampleRate, uint16_t bitsPerSample);
public:
WavePlayer (string audioDeviceName);
~WavePlayer();
bool isDeviceOpen ();
bool loadFile (string waveFileName);
bool play ();
};
WavePlayer::WavePlayer (string audioDeviceName)
: mAudioDevice (nullptr)
, mData (nullptr)
, mChannels (0)
, mSampleRate (0)
, mBitsPerSample (0)
, mFrameCount (0)
, mAudioDeviceName ()
, mWaveFileName ()
{
if (audioDeviceName.length() == 0)
mAudioDeviceName = "plughw:1,0";
else
mAudioDeviceName = audioDeviceName;
openDevice ();
}
WavePlayer::~WavePlayer()
{
snd_pcm_drain (mAudioDevice);
if (mAudioDevice != nullptr)
snd_pcm_close (mAudioDevice);
if (mData != nullptr)
free (mData);
}
bool WavePlayer:penDevice ()
{
int err;
err = snd_pcm_open(&mAudioDevice, mAudioDeviceName.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0)
{
cout << "Cannot open audio device " << mAudioDeviceName << " (" << snd_strerror(err) << ")" << endl;
mAudioDevice = nullptr;
return false;
}
return true;
}
bool WavePlayer::isDeviceOpen ()
{
return mAudioDevice != nullptr;
}
bool WavePlayer::setHwParams (uint32_t channels, uint32_t sampleRate, uint16_t bitsPerSample)
{
snd_pcm_format_t bits;
uint32_t resample = 1;
int err;
snd_pcm_state_t state = snd_pcm_state (mAudioDevice);
//cout << "setHwParams: PCM state " << to_string(state) << endl;
cout << "setHwParams: channels: " << to_string(channels) << " sample rate: " << to_string(sampleRate) << " bits: " << to_string(bitsPerSample) << endl;
if (channels == mChannels && sampleRate == mSampleRate && bitsPerSample == mBitsPerSample)
{
if ((err = snd_pcm_prepare (mAudioDevice)) < 0)
{
cout << "setHwParams: Error preparing audio device (" << snd_strerror(err) << ")" << endl;
return false;
}
return true;
}
mChannels = channels;
mSampleRate = sampleRate;
mBitsPerSample = bitsPerSample;
switch (mBitsPerSample)
{
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;
}
if (snd_pcm_hw_free (mAudioDevice) < 0)
{
/*
snd_pcm_drop (mAudioDevice);
snd_pcm_wait (mAudioDevice, 3000);
state = snd_pcm_state (mAudioDevice);
cout << "setHwParams: PCM state is " << to_string(state) << " after calling snd_pcm_drop" << endl;
*/
snd_pcm_drain (mAudioDevice);
snd_pcm_close (mAudioDevice);
openDevice ();
}
snd_pcm_hw_params_t *hwParams;
if ((err = snd_pcm_hw_params_malloc(&hwParams)) < 0)
{
cout << "setHwParams: Error initilizing parameter (" << snd_strerror(err) << ")" << endl;
return false;
}
if ((err = snd_pcm_hw_params_any(mAudioDevice, hwParams)) < 0)
{
cout << "setHwParams: Error getting parameter (" << snd_strerror(err) << ")" << endl;
goto error;
}
if ((err = snd_pcm_hw_params_set_rate_resample(mAudioDevice, hwParams, resample)) < 0)
{
cout << "setHwParams: Error setting re-sampling " << snd_strerror(err) << endl;
goto error;
}
if ((err = snd_pcm_hw_params_set_access(mAudioDevice, hwParams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
cout << "setHwParams: Error setting access type (" << snd_strerror(err) << ")" << endl;
goto error;
}
if ((err = snd_pcm_hw_params_set_format(mAudioDevice, hwParams, bits)) < 0)
{
cout << "setHwParams: Error setting sample format (" << snd_strerror(err) << ")" << endl;
goto error;
}
if ((err = snd_pcm_hw_params_set_channels(mAudioDevice, hwParams, channels)) < 0)
{
cout << "setHwParams: Error setting channel count (" << snd_strerror(err) << ")" << endl;
goto error;
}
if ((err = snd_pcm_hw_params_set_rate_near(mAudioDevice, hwParams, &sampleRate, 0)) < 0)
{
cout << "setHwParams: Error setting sample rate " << to_string (sampleRate) << " (" << snd_strerror(err) << ")" << endl;
goto error;
}
if ((err = snd_pcm_hw_params(mAudioDevice, hwParams)) < 0)
{
state = snd_pcm_state (mAudioDevice);
cout << "setHwParams: Error setting params (" << snd_strerror(err) << ") PCM state " << to_string(state) << endl;
goto error;
}
// snd_pcm_hw_params_get_buffer_size(hwParams, &bufferSize);
snd_pcm_hw_params_free (hwParams);
return true;
error:
snd_pcm_hw_params_free (hwParams);
return false;
}
void dumpDataHex (char* p, size_t size)
{
printf ("\n");
for (int i = 0; i < size; i++)
{
printf ("%02X ", *(p+i));
if ((i+1) % 16 == 0)
printf ("\n");
}
printf ("\n");
}
bool WavePlayer::loadFile (string waveFileName)
{
Header head;
Format format;
ChunkHead dataHead;
cout << endl;
cout << waveFileName << endl;
int file;
file = open (waveFileName.c_str(), O_RDONLY);
if (file < 0)
return false;
char text[5];
text [4] = 0;
string fmt;
read (file, &head, sizeof(Header));
read (file, &format, sizeof(Format));
if (format.length > sizeof (format)-
{
char b;
for (int i = 0; i < format.length - (sizeof (format)-; i++)
{
read (file, &b, 1);
}
}
int i = 0;
do
{
read (file, &dataHead, sizeof(ChunkHead));
//dumpDataHex ((char*)&dataHead, sizeof(ChunkHead));
memcpy (text, dataHead.id, 4);
fmt = text;
if (fmt == "data")
break;
i++;
lseek (file, -sizeof(ChunkHead)+1, SEEK_CUR);
} while (i < 100);
if (fmt != "data")
{
cout << "loadFile: Do not find start of data chunk" << endl;
return false;
}
#if 0
memcpy (text, head.id, 4);
fmt = text;
cout << fmt;
cout << " length: " << to_string(head.length);
memcpy (text, head.type, 4);
fmt = text;
cout << " " << fmt;
memcpy (text, format.id, 4);
fmt = text;
cout << " " << fmt;
cout << " length: " << to_string(format.length);
memcpy (text, dataHead.id, 4);
fmt = text;
cout << " " << fmt;
cout << " length: " << to_string(dataHead.length) << endl;
cout << " channels: " << to_string(format.channels) << endl;
cout << " samplesPerSec: " << to_string(format.samplesPerSec) << endl;
cout << " avgBytesPerSec: " << to_string(format.avgBytesPerSec) << endl;
cout << " blockAlign: " << to_string(format.blockAlign) << endl;
cout << " bitsPerSample: " << to_string(format.bitsPerSample) << endl;
#endif
if (mData != nullptr)
{
cout << "Wait for " << mWaveFileName << "..." << endl;
snd_pcm_drain (mAudioDevice);
cout << "Go for " << waveFileName << endl;
free (mData);
}
mDataSize = dataHead.length;
mData = (char *)malloc(mDataSize);
read (file, mData, mDataSize);
mFrameCount = head.length * 8 / ((uint32_t)format.bitsPerSample * (uint32_t)format.channels);
close(file);
mWaveFileName = waveFileName;
if (format.bitsPerSample == 32)
{
if (format.fmt == WAVE_FORMAT_IEEE_FLOAT)
cout << "Audio format is 32Bit IEEE float" << endl;
if (mDataSize % 4 != 0)
cout << "loadFile: Buffer size is not multiple of 4" << endl;
char* wave16 = (char *)malloc (mDataSize/2);
float min = 0.0f;
float max = 0.0f;
for (int i = 0; i < mDataSize; i += 4)
{
float f = *((float*)(mData+i));
if (f > max)
max = f;
if (f < min)
min = f;
}
float scaling = 1.0f;
if (max > scaling)
scaling = max;
if (min < -scaling)
scaling = -min;
//scaling *= 2.0f;
cout << "loadFile: 32bit float data are in between " << to_string(min) << " and " << to_string(max) << " => Use scaling of " << to_string(scaling) << endl;
//dumpDataHex (mWave, 64);
int16_t sample16;
int16_t* dest = (int16_t*)wave16;
for (int i = 0; i < mDataSize; i += 4)
{
float f = *((float*)(mData+i));
sample16 = (int16_t)((f / scaling) * 32767);
//sample16 = (int16_t)(*p);
*dest = sample16;
dest++;
}
free (mData);
mData = wave16;
mDataSize /= 2;
format.bitsPerSample = 16;
#if 0
{
int16_t sample16;
int16_t min = 0;
int16_t max = 0;
//dumpDataHex (mWave, 64);
for (int i = 0; i < mDataSize; i += 2)
{
sample16 = *((int16_t*)(mData+i));
if (sample16 > max)
max = sample16;
if (sample16 < min)
min = sample16;
}
cout << "loadFile: 16bit signed data are in between " << to_string(min) << " and " << to_string(max) << endl;
}
#endif
}
if (!setHwParams (format.channels, format.samplesPerSec, format.bitsPerSample))
{
free (mData);
mData = nullptr;
mWaveFileName = "";
return false;
}
return true;
}
bool WavePlayer:lay ()
{
snd_pcm_uframes_t count, frames;
cout << "Play " << mWaveFileName << " - " << to_string(mFrameCount) << " frames" << endl;
snd_pcm_state_t state = snd_pcm_state (mAudioDevice);
//cout << "PCM state " << to_string(state) << endl;
if (state == SND_PCM_STATE_XRUN)
{
int err;
if ((err = snd_pcm_prepare (mAudioDevice)) < 0)
{
cout << "Play: Error preparing audio device (" << snd_strerror(err) << ")" << endl;
return false;
}
}
count = 0;
do
{
frames = snd_pcm_writei (mAudioDevice, mData + count, mFrameCount - count);
if (frames < 0)
frames = snd_pcm_recover (mAudioDevice, frames, 0);
if (frames < 0)
{
cout << "Error playing " << mWaveFileName << " (" << snd_strerror(frames) << ")" << endl;
return false;
}
count += frames;
} while (count < mFrameCount);
return true;
}
int main(void)
{
{
string fName = "16BitMono.wav";
//fName = "/usr/share/sounds/alsa/Rear_Left.wav";
WavePlayer player ("hw:1,0");
if (!player.isDeviceOpen ())
cout << "Error opening audio device" << endl;
else if (!player.loadFile (fName))
cout << "Error loading file " << fName << endl;
else if (!player.play ())
{
cout << "Error playing sound" << fName << endl;
}
#if 1
fName = "32BitMono.wav";
//fName = "/usr/share/sounds/alsa/Rear_Left.wav";
if (!player.loadFile (fName))
cout << "Error loading file " << fName << endl;
else if (!player.play ())
{
cout << "Error playing sound" << fName << endl;
}
#endif
}
#if 1
{
string fName = "/usr/share/sounds/alsa/Rear_Left.wav";
WavePlayer player ("hw:1,0");
if (!player.isDeviceOpen ())
cout << "Error opening audio device" << endl;
else if (!player.loadFile (fName))
cout << "Error loading file " << fName << endl;
else
{
for (int i = 0; i < 2; i++)
{
if (!player.play ())
{
cout << "Error playing sound" << fName << endl;
break;
}
sleep (3);
}
}
}
#endif
}
Wie rufst du zenity eigentlich von c aus auf?
Lesezeichen