| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 1 | |
Hello. How can i play sound file with qt4, without NAS support. thanks. -- [ signature omitted ]
Am Samstag, 6. Januar 2007 10:02 schrieb Alexander: > Hello. > > How can i play sound file with qt4, without NAS support. by using 3rd-party libraries such as SDL. toby
Attachment:
Attachment:
pgpWGxUbK037a.pgp
Description: PGP signature
Message 3 in thread
Alexander wrote:
> Hello.
>
> How can i play sound file with qt4, without NAS support.
>
> thanks.
>
You can't.
Alsa has been part of the kernel for more than 3 years.
While simple sound management is taken care of by Qt for MS Win and OSX
platforms, a lot of people fail to understand why there is no alsa support.
I was so pissed off by this situation that I wrote a re-implementation of
QSound for Alsa (so that at least *I* could play sounds), and advertised it
on this very list, but it does not seem to raise the faintest interest at
trolltech's ...
--
[ signature omitted ]
Message 4 in thread
На Sat, 06 Jan 2007 11:24:27 +0100
eb <eb5@xxxxxxxxxx> записано:
>
> I was so pissed off by this situation that I wrote a re-implementation of
> QSound for Alsa (so that at least *I* could play sounds), and advertised it
> on this very list, but it does not seem to raise the faintest interest at
> trolltech's ...
>
mmmm...
can you send me your re-implementation of QSound?
please.
--
[ signature omitted ]
Message 5 in thread
Alexander wrote:
> ?? Sat, 06 Jan 2007 11:24:27 +0100
> eb <eb5@xxxxxxxxxx> ????????:
>
>>
>> I was so pissed off by this situation that I wrote a re-implementation of
>> QSound for Alsa (so that at least *I* could play sounds), and advertised
>> it on this very list, but it does not seem to raise the faintest interest
>> at trolltech's ...
>>
>
> mmmm...
> can you send me your re-implementation of QSound?
> please.
>
>
Please help yourself ...
Notice :
1) this code is derived from 'wavplay' and 'aplay', which are open source.
2) It is VERY straightforward, and fit my needs, so it may not be fully
working (i.e : no 'pause' / 'stop' function). Since I'm not a professionnal
coder myself, it won't respect any coding standards, and is probably
borked.
3) It will only play wav files, and will even play a faulty 'click' at the
end of *some* wav files. I have workd on this for hours without finding the
problem (does the same on OSX and MS W)
4) If you come up with something better, please share it (email address
below)
Header :
/***************************************************************************
* Copyright (C) 2006 by EB (yfh2@xxxxxxxxxxx) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifndef _AUDIO_H_
#define _AUDIO_H_
#include <QSound>
#include <alsa/asoundlib.h>
typedef struct
{ u_int32_t dwSize ;
u_int16_t wFormatTag ;
u_int16_t wChannels ;
u_int32_t dwSamplesPerSec ;
u_int32_t dwAvgBytesPerSec ;
u_int16_t wBlockAlign ;
u_int16_t wBitsPerSample ;
} WAVEFORMAT ;
class QAlsaSound : public QSound
{
Q_OBJECT
public :
QAlsaSound( const QString& filename, QObject* parent=0) ;
~QAlsaSound() {};
QString Path ;
bool initialise() ;
bool isAvailable() { return is_available ; }
bool is_available;
void play();
private:
/* ALSA parameters */
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
char *device ; /* playback device */
snd_pcm_uframes_t chunk_size, buffer_size;
size_t bits_per_sample, bits_per_frame, chunk_bytes;
/* File parser */
int fd; /* Open file descriptor or -1 */
char* findchunk(char* pstart, char* fourcc, size_t n);
WAVEFORMAT waveformat ;
u_long samples, datastart;
};
#endif // _AUDIO_H_
Code :
/***************************************************************************
* Copyright (C) 2006 by EB (yfh2@xxxxxxxxxxx) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "audio/audio.h"
#include <alsa/asoundlib.h>
#include <QSound>
#if WORDS_BIGENDIAN
#define SwapLE16(x) ((((u_int16_t)x)<<8)|(((u_int16_t)x)>>8))
#define SwapLE32(x) ((((u_int32_t)x)<<24)|((((u_int32_t)x)<<8)&0x00FF0000) \
|((((u_int32_t)x)>>8)&0x0000FF00)|(((u_int32_t)x)>>24))
#else
#define SwapLE16(x) (x)
#define SwapLE32(x) (x)
#endif
#ifdef Q_OS_LINUX
#include <alsa/asoundlib.h>
#endif
#define BUFFERSIZE 1024
QAlsaSound::QAlsaSound( const QString& filename, QObject* parent):
QSound(filename,parent)
{
Path = filename;
is_available = initialise();
}
bool QAlsaSound::initialise()
{
if (QSound::isAvailable())
return TRUE ;
#ifdef Q_OS_LINUX
char buffer [ BUFFERSIZE ] ;
//device = strdup("plughw:0,0"); /* playback device */
device = strdup("default"); /* playback device */
char* ptr ;
u_long databytes ;
snd_pcm_format_t format;
snd_pcm_hw_params_t *params;
int err;
/*
* Open the file for reading:
*/
//Path = "/home/eb/Packages/qgo.new/src/sounds/enter.wav";
//Path="/home/eb/Documents/travail.wav";
if ( (fd = open(Path.toLatin1().constData(),O_RDONLY)) < 0 ) {
fprintf(stdout,"Error Opening WAV file %s\n",Path.toLatin1().constData());
return FALSE;
}
if ( lseek(fd,0L,SEEK_SET) != 0L ) {
printf("Error nRewinding WAV file %s\n",Path.toLatin1().constData());
return FALSE; /* Wav file must be seekable device */
}
read (fd, buffer, BUFFERSIZE) ;
if (findchunk (buffer, "RIFF", BUFFERSIZE) != buffer) {
fprintf(stdout,"Bad format: Cannot find RIFF file marker\n"); /* wwg:
Report error */
return FALSE ;
}
if (! findchunk (buffer, "WAVE", BUFFERSIZE)) {
fprintf(stdout,"Bad format: Cannot find WAVE file marker\n"); /* wwg:
report error */
return FALSE ;
}
ptr = findchunk (buffer, "fmt ", BUFFERSIZE) ;
if (! ptr) {
fprintf(stdout,"Bad format: Cannot find 'fmt' file marker\n"); /* wwg:
report error */
return FALSE ;
}
ptr += 4 ; /* Move past "fmt ".*/
memcpy (&waveformat, ptr, sizeof (WAVEFORMAT)) ;
waveformat.dwSize = SwapLE32(waveformat.dwSize);
waveformat.wFormatTag = SwapLE16(waveformat.wFormatTag) ;
waveformat.wChannels = SwapLE16(waveformat.wChannels) ;
waveformat.dwSamplesPerSec = SwapLE32(waveformat.dwSamplesPerSec) ;
waveformat.dwAvgBytesPerSec = SwapLE32(waveformat.dwAvgBytesPerSec) ;
waveformat.wBlockAlign = SwapLE16(waveformat.wBlockAlign) ;
waveformat.wBitsPerSample = SwapLE16(waveformat.wBitsPerSample) ;
ptr = findchunk (buffer, "data", BUFFERSIZE) ;
if (! ptr) {
fprintf(stdout,"Bad format: unable to find 'data' file marker\n"); /* wwg:
report error */
return FALSE ;
}
ptr += 4 ; /* Move past "data".*/
memcpy (&databytes, ptr, sizeof (u_long)) ;
samples = databytes / waveformat.wBlockAlign ;
datastart = ((u_long) (ptr + 4)) - ((u_long) (&(buffer[0]))) ;
switch (waveformat.wBitsPerSample)
{
case 8:
format = SND_PCM_FORMAT_U8 ;
break;
case 16:
format = SND_PCM_FORMAT_S16_LE ;
break;
case 32 :
format = SND_PCM_FORMAT_S32_LE;
break;
default :
fprintf(stdout,"Bad format: %i bits per
seconds\n",waveformat.wBitsPerSample ); /* wwg: report error */
return FALSE ;
break;
}
//fprintf(stdout,"%s - format :%d, %i Hz, %i channels \n",Path.latin
(),waveformat.wBitsPerSample, waveformat.dwSamplesPerSec,
waveformat.wChannels);
/*
* ALSA pain
*/
snd_pcm_hw_params_alloca(¶ms);
if ((err = snd_pcm_open (&handle, device,
SND_PCM_STREAM_PLAYBACK,SND_PCM_ASYNC)) < 0) {
fprintf (stdout, "cannot open audio device %s
(%s)\n",
device,
snd_strerror (err));
return FALSE;
}
if ((err = snd_pcm_nonblock(handle, 1))< 0) {
fprintf (stdout,"nonblock setting error: %s", snd_strerror(err));
return FALSE;
}
/* Init hwparams with full configuration space */
if (snd_pcm_hw_params_any(handle, params) < 0) {
fprintf(stdout, "Can not configure this PCM device.\n");
return FALSE;
}
err = snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) {
fprintf(stdout,"Access type not available");
return FALSE;
}
err = snd_pcm_hw_params_set_format(handle, params, format);
if (err < 0) {
fprintf(stdout,"Sample format non available");
return FALSE;
}
err = snd_pcm_hw_params_set_channels(handle, params, waveformat.wChannels);
if (err < 0) {
fprintf(stdout,"Channels count non available");
return FALSE;
}
err = snd_pcm_hw_params_set_rate_near(handle, params,
&waveformat.dwSamplesPerSec, 0);
if (err < 0) {
fprintf(stdout,"Unable to set rate : %d", waveformat.dwSamplesPerSec);
return FALSE;
}
assert(err >= 0);
err = snd_pcm_hw_params(handle, params);
if (err < 0) {
fprintf(stdout,"Unable to install hw params:");
return FALSE;
}
chunk_size = 0;
buffer_size=0;
snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
bits_per_sample = snd_pcm_format_physical_width(format);
bits_per_frame = bits_per_sample * waveformat.wChannels;
chunk_bytes = chunk_size * bits_per_frame / 8;
return TRUE ;
#endif
}
void QAlsaSound::play()
{
if (!is_available)
return;
#ifdef Q_OS_LINUX
int err;
/*
* start playback
*/
err=lseek(fd,datastart,SEEK_SET);
//int written;
int count,f;
char *buffer2;
buffer2 = (char *)malloc (buffer_size);
while ((count = read (fd, buffer2,buffer_size)))
{
f=count*8/bits_per_frame;
while ((frames = snd_pcm_writei(handle, buffer2, f)) < 0)
snd_pcm_prepare(handle);
/******************************************************************************************
*
* Portion of code not used, because it does not change the playback
* quality on my box. This code is more or less part of aplay ot other
* players
*
* written=0;
* while (f > 0) {
*
* frames = snd_pcm_writei(handle, buffer2+written, f);
* if (frames == -EAGAIN || (frames >= 0 && frames < f))
* snd_pcm_wait(handle, 1000);
* else if (frames < 0)//{
* frames = snd_pcm_recover(handle, frames, 0);
* //snd_pcm_prepare(handle);//}
* if (frames < 0) {
* printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
* break;
* }
*
* if (frames > 0)
* {
* f -= frames;
* written += frames * bits_per_frame / 8;
* }
* }
*
*****************************************************************************************/
}
snd_pcm_drain(handle);
#else
QSound::play();
#endif
}
char* QAlsaSound::findchunk (char* pstart, char* fourcc, size_t n)
{ char *pend ;
int k, test ;
pend = pstart + n ;
while (pstart < pend)
{ if (*pstart == *fourcc) /* found match for first char*/
{ test = TRUE ;
for (k = 1 ; fourcc [k] != 0 ; k++)
test = (test ? ( pstart [k] == fourcc [k] ) : FALSE) ;
if (test)
return pstart ;
} ; /* if*/
pstart ++ ;
} ; /* while lpstart*/
return NULL ;
} /* findchuck*/
--
[ signature omitted ]