|
|
| version 1.5, 2004/05/22 16:35:08 | version 1.11, 2008/03/18 15:40:20 |
|---|---|
| Line 1 | Line 1 |
| /* $Id$ */ | |
| /* | /* |
| * Copyright (c) 2001-2003 NONAKA Kimihiro | * Copyright (c) 2001-2003 NONAKA Kimihiro |
| * All rights reserved. | * All rights reserved. |
| Line 10 | Line 12 |
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products | |
| * derived from this software without specific prior written permission. | |
| * | * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| Line 33 BYTE | Line 33 BYTE |
| snddrv_drv2num(const char* cfgstr) | snddrv_drv2num(const char* cfgstr) |
| { | { |
| if (strcasecmp(cfgstr, "NetBSD") == 0) | if (strcasecmp(cfgstr, "SDL") == 0) |
| return SNDDRV_NETBSD; | |
| else if (strcasecmp(cfgstr, "OSS") == 0) | |
| return SNDDRV_OSS; | |
| else if (strcasecmp(cfgstr, "ESD") == 0) | |
| return SNDDRV_ESD; | |
| else if (strcasecmp(cfgstr, "SDL") == 0) | |
| return SNDDRV_SDL; | return SNDDRV_SDL; |
| return SNDDRV_NODRV; | return SNDDRV_NODRV; |
| } | } |
| Line 49 snddrv_num2drv(BYTE num) | Line 43 snddrv_num2drv(BYTE num) |
| { | { |
| switch (num) { | switch (num) { |
| case SNDDRV_NETBSD: | |
| return "NetBSD"; | |
| case SNDDRV_OSS: | |
| return "OSS"; | |
| case SNDDRV_ESD: | |
| return "ESD"; | |
| case SNDDRV_SDL: | case SNDDRV_SDL: |
| return "SDL"; | return "SDL"; |
| } | } |
| Line 69 snddrv_num2drv(BYTE num) | Line 57 snddrv_num2drv(BYTE num) |
| #include "dosio.h" | #include "dosio.h" |
| #include "parts.h" | #include "parts.h" |
| #include "sysmng.h" | |
| #include "sound.h" | #include "sound.h" |
| #if defined(VERMOUTH_LIB) | #if defined(VERMOUTH_LIB) |
| #include "vermouth.h" | #include "vermouth.h" |
| #endif | |
| #include "sysmng.h" | |
| #if defined(VERMOUTH_LIB) | |
| MIDIMOD vermouth_module = NULL; | MIDIMOD vermouth_module = NULL; |
| #endif | #endif |
| Line 141 calc_fragment(UINT size) | Line 127 calc_fragment(UINT size) |
| return f; | return f; |
| } | } |
| void | static void |
| snddrv_setup(void) | snddrv_setup(void) |
| { | { |
| if (np2oscfg.snddrv < SNDDRV_DRVMAX) { | if (np2oscfg.snddrv < SNDDRV_DRVMAX) { |
| switch (np2oscfg.snddrv) { | switch (np2oscfg.snddrv) { |
| #if defined(USE_NETBSDAUDIO) | |
| case SNDDRV_NETBSD: | |
| netbsdaudio_setup(); | |
| return; | |
| #endif | |
| #if defined(USE_OSSAUDIO) | |
| case SNDDRV_OSS: | |
| ossaudio_setup(); | |
| return; | |
| #endif | |
| #if defined(USE_ESDAUDIO) | |
| case SNDDRV_ESD: | |
| esdaudio_setup(); | |
| return; | |
| #endif | |
| #if defined(USE_SDLAUDIO) || defined(USE_SDLMIXER) | #if defined(USE_SDLAUDIO) || defined(USE_SDLMIXER) |
| case SNDDRV_SDL: | case SNDDRV_SDL: |
| #if defined(USE_SDLMIXER) | #if defined(USE_SDLMIXER) |
| Line 187 snddrv_setup(void) | Line 158 snddrv_setup(void) |
| return; | return; |
| } else | } else |
| #endif | #endif |
| #if defined(USE_ESDAUDIO) | |
| if (esdaudio_setup() == SUCCESS) { | |
| np2oscfg.snddrv = SNDDRV_ESD; | |
| sysmng_update(SYS_UPDATEOSCFG); | |
| return; | |
| } else | |
| #endif | |
| #if defined(USE_OSSAUDIO) | |
| if (ossaudio_setup() == SUCCESS) { | |
| np2oscfg.snddrv = SNDDRV_OSS; | |
| sysmng_update(SYS_UPDATEOSCFG); | |
| return; | |
| } else | |
| #endif | |
| #if defined(USE_NETBSDAUDIO) | |
| if (netbsdaudio_setup() == SUCCESS) { | |
| np2oscfg.snddrv = SNDDRV_NETBSD; | |
| sysmng_update(SYS_UPDATEOSCFG); | |
| return; | |
| } else | |
| #endif | |
| { | { |
| /* Nothing to do */ | /* Nothing to do */ |
| /* fall thourgh "no match" */ | /* fall thourgh "no match" */ |
| Line 349 void | Line 299 void |
| soundmng_setreverse(BOOL reverse) | soundmng_setreverse(BOOL reverse) |
| { | { |
| #if defined(GCC_CPU_ARCH_IA32) | #if defined(GCC_CPU_ARCH_AMD64) |
| if (!reverse) { | |
| if (mmxflag & (MMXFLAG_NOTSUPPORT|MMXFLAG_DISABLE)) { | |
| fnmix = satuation_s16; | |
| } else { | |
| fnmix = saturation_s16mmx; | |
| } | |
| } else { | |
| fnmix = satuation_s16x; | |
| } | |
| #elif defined(GCC_CPU_ARCH_IA32) | |
| if (!reverse) { | if (!reverse) { |
| if (mmxflag & (MMXFLAG_NOTSUPPORT|MMXFLAG_DISABLE)) { | if (mmxflag & (MMXFLAG_NOTSUPPORT|MMXFLAG_DISABLE)) { |
| fnmix = _saturation_s16; | fnmix = _saturation_s16; |
| Line 586 nosound_setup(void) | Line 546 nosound_setup(void) |
| return SUCCESS; | return SUCCESS; |
| } | } |
| #if defined(USE_NETBSDAUDIO) || defined(USE_OSSAUDIO) || defined(USE_ESDAUDIO) | #if defined(GCC_CPU_ARCH_AMD64) |
| /* | void PARTSCALL |
| * common driver | _saturation_s16(SINT16 *dst, const SINT32 *src, UINT size) |
| */ | |
| static pthread_t ptid; | |
| static BOOL is_proc; | |
| static void * | |
| buffer_play(void *arg) | |
| { | { |
| char *buf; | asm volatile ( |
| size_t len = opna_frame; | "movq %0, %%rcx;" |
| size_t s; | "movq %1, %%rdx;" |
| ssize_t r; | "movl %2, %%ebx;" |
| int nextbuf; | "shrl $1, %%ebx;" |
| "je .ss16_ed;" | |
| UNUSED(arg); | ".ss16_lp:" |
| "movl (%%rdx), %%eax;" | |
| is_proc = TRUE; | "cmpl $0x000008000, %%eax;" |
| while (is_proc) { | "jl .ss16_min;" |
| nextbuf = sound_nextbuf; | "movw $0x7fff, %%ax;" |
| if (sound_event) | "jmp .ss16_set;" |
| memset(sound_event, 0, len); | ".ss16_min:" |
| sound_nextbuf = (sound_nextbuf + 1) % NSOUNDBUFFER; | "cmpl $0x0ffff8000, %%eax;" |
| sound_event = sound_buffer[sound_nextbuf]; | "jg .ss16_set;" |
| "movw $0x8001, %%ax;" | |
| buf = sound_buffer[nextbuf]; | ".ss16_set:" |
| s = 0; | "leal 4(%%rdx), %%edx;" |
| for (;;) { | "movw %%ax, (%%rcx);" |
| r = write(audio_fd, buf + s, len - s); | "decl %%ebx;" |
| if (r >= 0) { | "leal 2(%%rcx), %%ecx;" |
| s += r; | "jne .ss16_lp;" |
| if (len <= s) | ".ss16_ed:" |
| break; | : /* output */ |
| } | : "m" (dst), "m" (src), "m" (size) |
| } | : "ebx"); |
| } | |
| is_proc = FALSE; | |
| return NULL; | |
| } | } |
| void | void PARTSCALL |
| snddrv_play(void) | _saturation_s16x(SINT16 *dst, const SINT32 *src, UINT size) |
| { | { |
| if (pthread_create(&ptid, NULL, buffer_play, NULL) != 0) { | asm volatile ( |
| fprintf(stderr, "audio_play: can't create thread.\n"); | "movq %0, %%rcx;" |
| } | "movq %1, %%rdx;" |
| "movl %2, %%ebx;" | |
| "shrl $2, %%ebx;" | |
| "je .ss16x_ed;" | |
| ".ss16x_lp:" | |
| "movl (%%rdx), %%eax;" | |
| "cmpl $0x000008000, %%eax;" | |
| "jl .ss16xl_min;" | |
| "movw $0x7fff, %%ax;" | |
| "jmp .ss16xl_set;" | |
| ".ss16xl_min:" | |
| "cmpl $0x0ffff8000, %%eax;" | |
| "jg .ss16xl_set;" | |
| "movw $0x8001, %%ax;" | |
| ".ss16xl_set:" | |
| "movw %%ax, 2(%%rcx);" | |
| "movl 4(%%rdx), %%eax;" | |
| "cmpl $0x000008000, %%eax;" | |
| "jl .ss16xr_min;" | |
| "movw $0x7fff, %%ax;" | |
| "jmp .ss16xr_set;" | |
| ".ss16xr_min:" | |
| "cmpl $0x0ffff8000, %%eax;" | |
| "jg .ss16xr_set;" | |
| "mov $0x8001, %%ax;" | |
| ".ss16xr_set:" | |
| "movw %%ax, (%%rcx);" | |
| "leal 8(%%rdx), %%edx;" | |
| "decl %%ebx;" | |
| "leal 4(%%rcx), %%ecx;" | |
| "jne .ss16x_lp;" | |
| ".ss16x_ed:" | |
| : /* output */ | |
| : "m" (dst), "m" (src), "m" (size) | |
| : "ebx"); | |
| } | } |
| void | void PARTSCALL |
| snddrv_stop(void) | saturation_s16mmx(SINT16 *dst, const SINT32 *src, UINT size) |
| { | { |
| is_proc = FALSE; | asm volatile ( |
| "movq %0, %%rcx;" | |
| "movq %1, %%rdx;" | |
| "movl %2, %%eax;" | |
| "shrl $3, %%eax;" | |
| "je .ss16m_ed;" | |
| "pxor %%mm0, %%mm0;" | |
| ".ss16m_lp:" | |
| "movq (%%rdx), %%mm1;" | |
| "movq 8(%%rdx), %%mm2;" | |
| "packssdw %%mm2, %%mm1;" | |
| "leaq 16(%%rdx), %%rdx;" | |
| "movq %%mm1, (%%rcx);" | |
| "leaq 8(%%rcx), %%rcx;" | |
| "dec %%eax;" | |
| "jne .ss16m_lp;" | |
| "emms;" | |
| ".ss16m_ed:" | |
| : /* output */ | |
| : "m" (dst), "m" (src), "m" (size)); | |
| } | } |
| #elif defined(GCC_CPU_ARCH_IA32) | |
| #endif /* USE_NETBSDAUDIO || USE_OSSAUDIO || USE_ESDAUDIO */ | |
| #if defined(GCC_CPU_ARCH_IA32) | |
| void PARTSCALL | void PARTSCALL |
| _saturation_s16(SINT16 *dst, const SINT32 *src, UINT size) | _saturation_s16(SINT16 *dst, const SINT32 *src, UINT size) |
| { | { |
| Line 746 saturation_s16mmx(SINT16 *dst, const SIN | Line 746 saturation_s16mmx(SINT16 *dst, const SIN |
| : /* output */ | : /* output */ |
| : "m" (dst), "m" (src), "m" (size)); | : "m" (dst), "m" (src), "m" (size)); |
| } | } |
| #endif /* __GNUC__ && GCC_CPU_ARCH_IA32 */ | #endif /* GCC_CPU_ARCH_AMD64 */ |
| #if defined(USE_SDLAUDIO) || defined(USE_SDLMIXER) | |
| #include <SDL.h> | |
| static void sdlaudio_callback(void *, unsigned char *, int); | |
| #if defined(USE_SDLAUDIO) | |
| static BOOL | |
| sdlaudio_init(UINT rate, UINT samples) | |
| { | |
| static SDL_AudioSpec fmt; | |
| int rv; | |
| fmt.freq = rate; | |
| fmt.format = AUDIO_S16SYS; | |
| fmt.channels = 2; | |
| fmt.samples = samples; | |
| fmt.callback = sdlaudio_callback; | |
| fmt.userdata = (void *)(samples * 2 * sizeof(SINT16)); | |
| rv = SDL_Init(SDL_INIT_AUDIO); | |
| if (rv < 0) { | |
| fprintf(stderr, "sdlaudio_init: SDL_Init\n"); | |
| return FAILURE; | |
| } | |
| audio_fd = SDL_OpenAudio(&fmt, NULL); | |
| if (audio_fd < 0) { | |
| fprintf(stderr, "sdlaudio_init: SDL_OpenAudio\n"); | |
| SDL_Quit(); | |
| return FAILURE; | |
| } | |
| return SUCCESS; | |
| } | |
| static BOOL | |
| sdlaudio_term(void) | |
| { | |
| SDL_CloseAudio(); | |
| SDL_Quit(); | |
| return SUCCESS; | |
| } | |
| static void | |
| sdlaudio_play(void) | |
| { | |
| SDL_PauseAudio(0); | |
| } | |
| static void | |
| sdlaudio_stop(void) | |
| { | |
| SDL_PauseAudio(1); | |
| } | |
| BOOL | |
| sdlaudio_setup(void) | |
| { | |
| snddrv.drvinit = sdlaudio_init; | |
| snddrv.drvterm = sdlaudio_term; | |
| snddrv.sndplay = sdlaudio_play; | |
| snddrv.sndstop = sdlaudio_stop; | |
| snddrv.pcmload = nosound_pcmload; | |
| snddrv.pcmdestroy = nosound_pcmdestroy; | |
| snddrv.pcmplay = nosound_pcmplay; | |
| snddrv.pcmstop = nosound_pcmstop; | |
| snddrv.pcmvolume = nosound_pcmvolume; | |
| return SUCCESS; | |
| } | |
| #endif /* USE_SDLAUDIO */ | |
| #if defined(USE_SDLMIXER) | |
| #include <SDL_mixer.h> | |
| static BOOL | |
| sdlmixer_init(UINT rate, UINT samples) | |
| { | |
| int rv; | |
| rv = SDL_Init(SDL_INIT_AUDIO); | |
| if (rv < 0) { | |
| fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError()); | |
| goto failure; | |
| } | |
| rv = Mix_OpenAudio(rate, AUDIO_S16SYS, 2, samples); | |
| if (rv < 0) { | |
| fprintf(stderr, "Mix_OpenAudio(): %s\n", Mix_GetError()); | |
| goto failure1; | |
| } | |
| SDL_PauseAudio(1); | |
| rv = Mix_AllocateChannels(SOUND_MAXPCM); | |
| if (rv < 0) { | |
| fprintf(stderr, "Mix_AllocateChannels(): %s\n", Mix_GetError()); | |
| goto failure2; | |
| } | |
| Mix_HookMusic(sdlaudio_callback, (void*)(samples * 2 * sizeof(SINT16))); | |
| return SUCCESS; | |
| failure2: | |
| Mix_CloseAudio(); | |
| failure1: | |
| SDL_Quit(); | |
| failure: | |
| return FAILURE; | |
| } | |
| static BOOL | |
| sdlmixer_term(void) | |
| { | |
| Mix_CloseAudio(); | |
| SDL_Quit(); | |
| return SUCCESS; | |
| } | |
| static void | |
| sdlmixer_play(void) | |
| { | |
| SDL_PauseAudio(0); | |
| } | |
| static void | |
| sdlmixer_stop(void) | |
| { | |
| SDL_PauseAudio(1); | |
| } | |
| static void * | |
| sdlmixer_pcmload(UINT num, const char *path) | |
| { | |
| Mix_Chunk *chunk; | |
| UNUSED(num); | |
| chunk = Mix_LoadWAV(path); | |
| return (void *)chunk; | |
| } | |
| static void | |
| sdlmixer_pcmdestroy(void *chanp, UINT num) | |
| { | |
| Mix_Chunk *chunk = (Mix_Chunk *)chanp; | |
| Mix_HaltChannel(num); | |
| Mix_FreeChunk(chunk); | |
| } | |
| static void | |
| sdlmixer_pcmplay(void *chanp, UINT num, BOOL loop) | |
| { | |
| Mix_Chunk *chunk = (Mix_Chunk *)chanp; | |
| Mix_PlayChannel(num, chunk, loop ? -1 : 1); | |
| } | |
| static void | |
| sdlmixer_pcmstop(void *chanp, UINT num) | |
| { | |
| UNUSED(chanp); | |
| Mix_HaltChannel(num); | |
| } | |
| static void | |
| sdlmixer_pcmvolume(void *chanp, UINT num, int volume) | |
| { | |
| UNUSED(chanp); | |
| Mix_Volume(num, (MIX_MAX_VOLUME * volume) / 100); | |
| } | |
| BOOL | |
| sdlmixer_setup(void) | |
| { | |
| snddrv.drvinit = sdlmixer_init; | |
| snddrv.drvterm = sdlmixer_term; | |
| snddrv.sndplay = sdlmixer_play; | |
| snddrv.sndstop = sdlmixer_stop; | |
| snddrv.pcmload = sdlmixer_pcmload; | |
| snddrv.pcmdestroy = sdlmixer_pcmdestroy; | |
| snddrv.pcmplay = sdlmixer_pcmplay; | |
| snddrv.pcmstop = sdlmixer_pcmstop; | |
| snddrv.pcmvolume = sdlmixer_pcmvolume; | |
| return SUCCESS; | |
| } | |
| #endif /* USE_SDLMIXER */ | |
| static void | |
| sdlaudio_callback(void *userdata, unsigned char *stream, int len) | |
| { | |
| UINT samples = (UINT)userdata; | |
| int nextbuf = sound_nextbuf; | |
| UNUSED(len); | |
| if (sound_event != NULL) | |
| memset(sound_event, 0, samples); | |
| sound_nextbuf = (sound_nextbuf + 1) % NSOUNDBUFFER; | |
| sound_event = sound_buffer[sound_nextbuf]; | |
| SDL_MixAudio(stream, (const void *)sound_buffer[nextbuf], samples, | |
| SDL_MIX_MAXVOLUME); | |
| } | |
| #endif /* USE_SDLAUDIO || USE_SDLMIXER */ | |
| #endif /* !NOSOUND */ | #endif /* !NOSOUND */ |