📄 i_sound.c
字号:
// Pitching (that is, increased speed of playback)
// is set, but currently not used by mixing.
//
int
I_StartSound
( int id,
int vol,
int sep,
int pitch,
int priority )
{
if (nosound)
return -1;
// Debug.
//printf( "I_StartSound: starting sound %d\n", id );
// Returns a handle (not used).
id = addsfx( id, vol, steptable[pitch], sep );
// fprintf( stderr, "/handle is %d\n", id );
return id;
}
void I_StopSound (int handle)
{
// You need the handle returned by StartSound.
// Would be looping all channels,
// tracking down the handle,
// an setting the channel to zero.
// UNUSED.
handle = 0;
}
int I_SoundIsPlaying(int handle)
{
// Ouch.
return gametic < handle;
}
//
// This function loops all active (internal) sound
// channels, retrieves a given number of samples
// from the raw sound data, modifies it according
// to the current (internal) channel parameters,
// mixes the per channel samples into the global
// mixbuffer, clamping it to the allowed range,
// and sets up everything for transferring the
// contents of the mixbuffer to the (two)
// hardware channels (left and right, that is).
//
// This function currently supports only 16bit.
//
void I_UpdateSound( void )
{
// Mix current sound data.
// Data, from raw sound, for right and left.
register unsigned int sample;
register int dl;
register int dr;
// Pointers in global mixbuffer, left, right, end.
signed short* leftout;
signed short* rightout;
signed short* leftend;
// Step in mixbuffer, left and right, thus two.
int step;
// Mixing channel index.
int chan;
// Left and right channel
// are in global mixbuffer, alternating.
leftout = pmData->MixBuffers[ pmData->FillBuffer].pBuffer;
rightout = leftout+1;// pmData->BufferParms.ulBufferSize/2;
// next fill buffer
pmData->FillBuffer++;
if (pmData->FillBuffer >= pmData->BufferParms.ulNumBuffers)
pmData->FillBuffer = 0;
step = 2;
// Determine end, for left channel only
// (right channel is implicit).
// ulBufferSize is len in bytes (8 bit), ulBufferSize/2 is 16bit length
leftend = leftout + pmData->BufferParms.ulBufferSize/2;
// Mix sounds into the mixing buffer.
// Loop over step*SAMPLECOUNT,
// that is 512 values for two channels.
while (leftout != leftend)
{
// Reset left/right value.
dl = 0;
dr = 0;
// Love thy L2 chache - made this a loop.
// Now more channels could be set at compile time
// as well. Thus loop those channels.
for ( chan = 0; chan < NUM_CHANNELS; chan++ )
{
// Check channel, if active.
if (channels[ chan ])
{
//printf( "I_UpdateSound: channel %d active\n", chan);
// Get the raw data from the channel.
sample = *channels[ chan ];
// Add left and right part
// for this channel (sound)
// to the current data.
// Adjust volume accordingly.
dl += channelleftvol_lookup[ chan ][sample];
dr += channelrightvol_lookup[ chan ][sample];
// Increment index ???
channelstepremainder[ chan ] += channelstep[ chan ];
// MSB is next sample???
channels[ chan ] += channelstepremainder[ chan ] >> 16;
// Limit to LSB???
channelstepremainder[ chan ] &= 65536-1;
// Check whether we are done.
if (channels[ chan ] >= channelsend[ chan ])
channels[ chan ] = 0;
}
}
// Clamp to range. Left hardware channel.
// Has been char instead of short.
// if (dl > 127) *leftout = 127;
// else if (dl < -128) *leftout = -128;
// else *leftout = dl;
//dl <<= 4;
//dr <<= 4;
if (dl > 0x7fff)
*leftout = 0x7fff;
else if (dl < -0x8000)
*leftout = -0x8000;
else
*leftout = dl;
// Same for right hardware channel.
if (dr > 0x7fff)
*rightout = 0x7fff;
else if (dr < -0x8000)
*rightout = -0x8000;
else
*rightout = dr;
// Increment current pointers in mixbuffer.
leftout += step;
rightout += step;
/*
// mono out
*leftout = (dl+dr)/2;
leftout++;
rightout++;
*/
}
}
//
// This would be used to write out the mixbuffer
// during each game loop update.
// Updates sound buffer and audio device at runtime.
// It is called during Timer interrupt with SNDINTR.
// Mixing now done synchronous, and
// only output be done asynchronous?
//
void
I_SubmitSound(void)
{
// Write it to DSP device.
write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
}
void
I_UpdateSoundParams
( int handle,
int vol,
int sep,
int pitch)
{
// I fail too see that this is used.
// Would be using the handle to identify
// on which channel the sound might be active,
// and resetting the channel parameters.
// UNUSED.
handle = vol = sep = pitch = 0;
}
void I_ShutdownSound(void)
{
// Wait till all pending sounds are finished.
int done = 0;
int i;
//added:03-01-98:
if( !sound_started )
return;
// FIXME (below).
printf( "I_ShutdownSound: NOT finishing pending sounds\n");
while ( !done )
{
for( i=0 ; i<8 && !channels[i] ; i++);
// FIXME. No proper channel output.
//if (i==8)
done=1;
DosSleep( 100); // wait 0.1 sec
}
ShutdownDART( pmData);
// Done.
sound_started = false;
return;
}
void I_StartupSound()
{
int i;
if (nosound)
return;
// init dart audio
InitDART( pmData);
// Secure and configure sound device first.
// Initialize external data (all sounds) at start, keep static.
printf( "I_InitSound\n");
for (i=1 ; i<NUMSFX ; i++)
{
// Alias? Example is the chaingun sound linked to pistol.
if (!S_sfx[i].link)
{
// Load data from WAD file.
S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
}
else
{
// Previously loaded already?
S_sfx[i].data = S_sfx[i].link->data;
lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
}
}
printf( "I_InitSound: pre-cached all sound data\n");
// Now initialize mixbuffer with zero.
for ( i = 0; i< MIXBUFFERSIZE; i++ )
mixbuffer[i] = 0;
I_SetChannels();
// Finished initialization.
printf( "I_InitSound: sound module ready\n");
//added:08-01-98:we use a similar startup/shutdown scheme as Allegro.
I_AddExitFunc(I_ShutdownSound);
sound_started = true;
}
//
// MUSIC API.
// Still no music done.
// Remains. Dummies.
//
void I_InitMusic(void)
{
printf( "I_InitMusic\n");
if (nomusic)
return;
// initialisation of midicard by I_StartupSound
pMus2MidData = (char *)Z_Malloc (MIDBUFFERSIZE,PU_STATIC,NULL);
I_AddExitFunc(I_ShutdownMusic);
music_started = true;
}
void I_ShutdownMusic(void)
{
printf( "I_ShutdownMusic\n");
if (!music_started)
return;
I_StopSong( 0);
I_UnRegisterSong( 0);
music_started=false;
}
void I_PlaySong(int handle, int looping)
{
if (nomusic)
return;
printf( "I_PlaySong looping=%d\n", looping);
PlayMIDI( pmData, looping);
// need to set volume again, because before midi device was closed
SetMIDIVolume( pmData, cv_musicvolume.value);
}
void I_PauseSong (int handle)
{
if (nomusic)
return;
PauseMIDI( pmData);
}
void I_ResumeSong (int handle)
{
if (nomusic)
return;
// UNUSED.
handle = 0;
ResumeMIDI( pmData);
}
void I_StopSong(int handle)
{
if (nomusic)
return;
// UNUSED.
ShutdownMIDI( pmData);
}
void I_UnRegisterSong(int handle)
{
if (nomusic)
return;
// UNUSED.
handle = 0;
printf( "I_UnRegisterSong\n");
// remove files
unlink( "doom.mid");
unlink( "doom.mus");
}
// ---------------
// I_SaveMemToFile
// Save as much as iLength bytes starting at pData, to
// a new file of given name. The file is overwritten if it is present.
// ---------------
void I_SaveMemToFile (unsigned char* pData, unsigned long iLength, char* sFileName)
{
int fileHandle;
fileHandle = open( sFileName, O_CREAT | O_BINARY | O_TRUNC | O_WRONLY,
S_IWRITE);
if (fileHandle == -1)
{
I_Error ("SaveMemToFile");
}
write( fileHandle, pData, iLength);
close( fileHandle);
}
int I_RegisterSong(void* data, int len)
{
int iErrorCode;
char* pMidiFileData = NULL; // MIDI music buffer to be played or NULL
int iMus2MidSize; // size of Midi output data
FILE* blah;
if (nomusic)
return 1;
/*
#ifdef DEBUGMIDISTREAM
CONS_Printf("I_RegisterSong: \n");
#endif
if (!memcmp(data,"MUS",3))
{
// convert mus to mid with a wonderful function
// thanks to S.Bacquet for the sources of qmus2mid
// convert mus to mid and load it in memory
if((iErrorCode = qmus2mid((char *)data,pMus2MidData,89,64,0,len,MIDBUFFERSIZE,
&iMus2MidSize))!=0)
{
CONS_Printf("Cannot convert mus to mid, converterror :%d\n",iErrorCode);
return 0;
}
pMidiFileData = pMus2MidData;
}
else
// support mid file in WAD !!! (no conversion needed)
if (!memcmp(data,"MThd",4))
{
pMidiFileData = data;
}
else
{
CONS_Printf ("Music lump is not MID or MUS music format\n");
return 0;
}
if (pMidiFileData == NULL)
{
CONS_Printf ("Not a valid MIDI file : %d\n",iErrorCode);
return 0;
}
#ifdef DEBUGMIDISTREAM //EVENMORE
else
{
I_SaveMemToFile (pMidiFileData, iMus2MidSize, "c:/temp/debug.mid");
}
#endif
I_SaveMemToFile (pMidiFileData, iMus2MidSize, "doom.mid");
*/
I_SaveMemToFile (data, len, "doom.mus");
qmus2mid( "doom.mus", "doom.mid", 0, 89,64,1);
OpenMIDI( pmData);
return 1;
}
// Is the song playing?
int I_QrySongPlaying(int handle)
{
// UNUSED.
handle = 0;
printf( "I_QrySongPlaying\n");
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -