Moved wave format conversion code to the sound lowlevel base class and added

format conversion support to the ALSA and OSS sound modules.
This commit is contained in:
Volker Ruppert 2015-01-24 21:01:45 +00:00
parent e37498025e
commit 2c621601cb
8 changed files with 81 additions and 64 deletions

View File

@ -320,24 +320,30 @@ int bx_sound_alsa_c::alsa_pcm_write()
return BX_SOUNDLOW_OK;
}
int bx_sound_alsa_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param)
int bx_sound_alsa_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
{
if (memcmp(param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {
startwaveplayback(param->samplerate, param->bits, param->channels == 2,
param->format);
pcm_param = *param;
int len2;
if (memcmp(src_param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {
startwaveplayback(src_param->samplerate, 16, 1, 1);
pcm_param = *src_param;
cvt_mult = 1;
if (src_param->bits == 8) cvt_mult = 2;
if (src_param->channels == 1) cvt_mult *= 2;
}
len2 = length * cvt_mult;
if (!alsa_pcm[0].handle) {
// Alert indicating that caller is probably erroneous
BX_ERROR(("sendwavepacket(): pcm is not open"));
return BX_SOUNDLOW_ERR;
}
if ((alsa_pcm[0].audio_bufsize+length) <= BX_SOUND_ALSA_BUFSIZE) {
memcpy(audio_buffer[0]+alsa_pcm[0].audio_bufsize, data, length);
alsa_pcm[0].audio_bufsize += length;
} else {
if ((alsa_pcm[0].audio_bufsize+len2) > BX_SOUND_ALSA_BUFSIZE) {
len2 = BX_SOUND_ALSA_BUFSIZE - alsa_pcm[0].audio_bufsize;
BX_ERROR(("ALSA: audio buffer overflow"));
return BX_SOUNDLOW_ERR;
}
if (len2 > 0) {
convert_wavedata(data, length, audio_buffer[0]+alsa_pcm[0].audio_bufsize, len2, src_param);
alsa_pcm[0].audio_bufsize += len2;
}
if (alsa_pcm[0].audio_bufsize < alsa_pcm[0].alsa_bufsize) {
return BX_SOUNDLOW_OK;

View File

@ -44,7 +44,7 @@ public:
virtual int openwaveoutput(const char *wavedev);
virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format);
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param);
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param);
virtual int stopwaveplayback();
virtual int closewaveoutput();

View File

@ -191,18 +191,26 @@ int bx_sound_linux_c::startwaveplayback(int frequency, int bits, bx_bool stereo,
return BX_SOUNDLOW_OK;
}
int bx_sound_linux_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param)
int bx_sound_linux_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
{
if (memcmp(param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {
startwaveplayback(param->samplerate, param->bits, param->channels == 2,
param->format);
pcm_param = *param;
int len2;
Bit8u *tmpbuffer;
if (memcmp(src_param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {
startwaveplayback(src_param->samplerate, 16, 1, 1);
pcm_param = *src_param;
cvt_mult = 1;
if (src_param->bits == 8) cvt_mult = 2;
if (src_param->channels == 1) cvt_mult *= 2;
}
if (wave_fd[0] == -1) {
return BX_SOUNDLOW_ERR;
}
int ret = write(wave_fd[0], data, length);
len2 = length * cvt_mult;
tmpbuffer = (Bit8u*)malloc(len2);
convert_wavedata(data, length, tmpbuffer, len2, src_param);
int ret = write(wave_fd[0], tmpbuffer, len2);
free(tmpbuffer);
if (ret == length) {
return BX_SOUNDLOW_OK;
} else {

View File

@ -41,7 +41,7 @@ public:
virtual int openwaveoutput(const char *wavedev);
virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format);
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param);
virtual int sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param);
virtual int stopwaveplayback();
virtual int closewaveoutput();

View File

@ -89,6 +89,49 @@ int bx_sound_lowlevel_c::startwaveplayback(int frequency, int bits, bx_bool ster
return BX_SOUNDLOW_OK;
}
void bx_sound_lowlevel_c::convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)
{
int i, j;
Bit8u xor_val;
xor_val = (param->format & 1) ? 0x00 : 0x80;
if (param->bits == 16) {
if ((param->format & 1) && (param->channels == 2)) {
memcpy(dst, src, dstsize);
} else if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
}
} else {
if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
}
}
}
int bx_sound_lowlevel_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *param)
{
if (memcmp(param, &pcm_param, sizeof(bx_pcm_param_t)) != 0) {

View File

@ -89,12 +89,17 @@ public:
virtual int register_wave_callback(void *, get_wave_cb_t wd_cb) {return -1;}
virtual void unregister_wave_callback(int callback_id) {}
protected:
void convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param);
bx_pcm_param_t pcm_param;
int cvt_mult;
int cb_count;
struct {
void *device;
get_wave_cb_t cb;
} get_wave[BX_MAX_WAVE_CALLBACKS];
int record_timer_index;
int record_packet_size;
sound_record_handler_t record_handler;

View File

@ -151,49 +151,6 @@ int bx_sound_sdl_c::startwaveplayback(int frequency, int bits, bx_bool stereo, i
return BX_SOUNDLOW_OK;
}
void bx_sound_sdl_c::convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param)
{
int i, j;
Bit8u xor_val;
xor_val = (param->format & 1) ? 0x00 : 0x80;
if (param->bits == 16) {
if ((param->format & 1) && (param->channels == 2)) {
memcpy(dst, src, dstsize);
} else if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i+=2) {
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
dst[j++] = src[i];
dst[j++] = src[i+1] ^ xor_val;
}
}
} else {
if (param->channels == 2) {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
} else {
j = 0;
for (i = 0; i < srcsize; i++) {
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
dst[j++] = 0;
dst[j++] = src[i] ^ xor_val;
}
}
}
}
int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[], bx_pcm_param_t *src_param)
{
int ret = BX_SOUNDLOW_OK;

View File

@ -42,11 +42,9 @@ public:
virtual void unregister_wave_callback(int callback_id);
void get_wave_data(Bit8u *stream, int len);
private:
void convert_wavedata(Bit8u *src, int srcsize, Bit8u *dst, int dstsize, bx_pcm_param_t *param);
bx_bool WaveOpen;
SDL_AudioSpec fmt;
int pcm_callback_id;
int cvt_mult;
};
#endif // BX_WITH_SDL || BX_WITH_SDL2