Newbie Spin Question
NWCCTV
Posts: 3,629
Being new to Spin I am not even sure if this is possible so go easy on me. If it is not possible suggestions are welcome. I have modified the Pressure Sensor Bar Graph Demo program to start and stop various servos depending on the rawReading received. Now I need tp play some .wav files pretty much at the same time. If I include one of the .wav/sd card reading programs from the OBEX in my Objects section, is there a way to call the "read SD card and Play .wav file functions from that program?
Comments
obj
music : "name_of_object_here"
then in your program you can call any of its public methods like this:
music.name_of_method
Edit: Here is the .wav/sd card code:
You have to name the PUB function!
electrodude
If your code looks like this now:
Then in the part of your program you want the wav to play you just put a call to Chimes, ie just place the word "Chimes" without quotes there
The PUB and PRI methods sit there waiting to do their code in your program and only execute their code when called by your program.
What you are showing is the method to play the wav file, which directs to Rayman's Wav Player method but you have to call this first by putting the word chimes somewhere else in the program.
The method PUB Chimes will not do anything until called.
Can you show the whole code and the part of your program where you wish the wav to play and I can then show you how to call the Chimes method.
EDIT: if that is Kye's demo file posted above it shows how to start it. Make sure the chimes.wav is in the folder his engine wants to see it in - probably the folder the engine is in.
//
// Author: Kwabena W. Agyeman
// Updated: 7/20/2011
// Designed For: P8X32A
// Version: 1.3
//
// Copyright (c) 2011 Kwabena W. Agyeman
// See end of file for terms of use.
//
// Update History:
//
// v1.0 - Original release - 7/27/2010.
// v1.1 - Merged object with player - 7/6/2011.
// v1.2 - Fixed playback issue - 7/18/2011.
// v1.3 - Added dither cog - 7/20/2011.
//
// For each included copy of this object only one spin interpreter should access it at a time.
//
// Nyamekye,
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Audio Circuit:
//
// 100OHM 1UF
// Left Pin Number --R
C-- Left Out (Use better audio circuit filtering for noise issues).
// |
// C 10NF
// |
// GND
//
// 100OHM 1UF
// Right Pin Number --R
C-- Right Out (Use better audio circuit filtering for noise issues).
// |
// C 10NF
// |
// GND
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}}
OBJ fat: "SD-MMC_FATEngine.spin"
VAR
long leftValue, rightValue, samplesPerSecond, clocksPerSample, numberOfSamples, samplePosition, ditherLeft, ditherRight
word dataBlock[512], callerPointer, callePointer, leftVolume, rightVolume, numberOfChannels, bitsPerSample
byte stopedOrStarted, beginOrEnd, cogIdentification, ditherCogIdentification
PUB leftChannelOutput '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the current sample going out to the left audio channel. The value returned is a 16 bit signed extended number.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return leftValue
PUB rightChannelOutput '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the current sample going out to the right audio channel. The value returned is a 16 bit signed extended number.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return rightValue
PUB fileSampleRateSetup(sampleRate) '' 4 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Setups the sample rate of the audio file. The samples are played at the sample rate.
'' //
'' // SampleRate - The new sample rate to playback sample at. Between 1 - 66,150 samples per second.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
clocksPerSample := (clkfreq / ((sampleRate <# 66_150) #> 1))
PUB fileSampleRate '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the sample rate of the audio file. The samples are played at the sample rate.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return samplesPerSecond
PUB fileSampleNumber '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the number of samples in the audio file. The samples are played at the sample rate.
'' //
'' // Valid while method "wavePlayerState" returns true.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return numberOfSamples
PUB fileSamplePosition '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the playback sample position in the audio file. The samples are played at the sample rate.
'' //
'' // Valid while method "wavePlayerState" returns true.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return (numberOfSamples - samplePosition)
PUB leftChannelVolume(newVolume) '' 4 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the volume of the left channel. (0 to 100).
'' //
'' // NewVolume - New volume to output at. Zero mutes the channel.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
leftVolume := (((newVolume <# 100) #> 0) * constant($1_00_00 / 100))
PUB rightChannelVolume(newVolume) '' 4 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Changes the volume of the right channel. (0 to 100).
'' //
'' // NewVolume - New volume to output at. Zero mutes the channel.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
rightVolume := (((newVolume <# 100) #> 0) * constant($1_00_00 / 100))
PUB pauseWavePlayer(state) '' 4 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Pause or unpause the wave player. The method "wavePlayerState" has nothing to do with the wave player being paused.
'' //
'' // State - New wave player state. True for paused and false for unpaused.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
stopedOrStarted := (not(not(state)))
PUB wavePlayerState '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Returns the wave player's state. True while playing a WAV file and false while not playing a WAV file.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
result or= beginOrEnd
PUB playWAVFile(filePathName) '' 56 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Plays a WAV file on the SD/MMC card - supports WAV files up to ~2GB and over ~1 second of audio.
'' //
'' // The WAV player supports 8-Bit 1/2 channel WAV files sampled between 1 Hz to 44,100 Hz.
'' //
'' // The WAV player supports 16-Bit 1/2 channel WAV files sampled between 1 Hz to 44,100 Hz.
'' //
'' // If an error occurs while reading the WAV file a string describing that error will be returned. Null otherwise.
'' //
'' // If an error occurs while reading the FAT file system a string describing that error will be returned. Null otherwise.
'' //
'' // FilePathName - A file system path string specifying the path of the WAV file to play.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
result := \playWAV(filePathName)
\fat.unmountPartition
PRI playWAV(filePathName) | chunkSkip, blockAlign, byteRate, searchChunkSize ' 52 Stack Longs
ifnot(fat.partitionMounted)
fat.mountPartition(0)
fat.openFile(filePathName, "R")
if(fat.readLong <> $46_46_49_52)
abort string("Not A RIFF File")
if((fat.readLong + 8) <> fat.fileSize)
abort string("RIFF Chunk Size Invalid")
if(fat.readLong <> $45_56_41_57)
abort string("Not A WAVE File")
repeat while(fat.readLong <> $20_74_6D_66)
searchChunkSize := fat.readLong
if((searchChunkSize < 1) or (fat.fileSize == fat.fileTell))
abort string("FMT Chunk Missing")
fat.fileSeek(searchChunkSize + fat.fileTell)
chunkSkip := (fat.readLong - 16)
if(chunkSkip < 0)
abort string("FMT Chunk Size Invalid")
if(fat.readShort <> 1)
abort string("Not A LPCM file")
numberOfChannels := fat.readShort
if((numberOfChannels < 1) or (2 < numberOfChannels))
abort string("Unsupported Number Of Channels")
samplesPerSecond := fat.readLong
if((samplesPerSecond < 1) or (44_100 < samplesPerSecond))
abort string("Unsupported Samples Per Second")
clocksPerSample := (clkfreq / samplesPerSecond)
byteRate := fat.readLong
blockAlign := fat.readShort
if((blockAlign <> 1) and (blockAlign <> 2) and (blockAlign <> 4))
abort string("Unsupported Block Align")
if(byteRate <> (samplesPerSecond * blockAlign))
abort string("Invalid Byte Rate")
bitsPerSample := fat.readShort
if((bitsPerSample <> 8) and (bitsPerSample <> 16))
abort string("Unsupported Bits Per Sample")
fat.fileSeek(chunkSkip + fat.fileTell)
repeat while(fat.readLong <> $61_74_61_64)
searchChunkSize := fat.readLong
if((searchChunkSize < 1) or (fat.fileSize == fat.fileTell))
abort string("DATA Chunk Missing")
fat.fileSeek(searchChunkSize + fat.fileTell)
numberOfSamples := (fat.readLong / blockAlign)
callerPointer := callePointer
repeat while(callerPointer == callePointer)
fat.readData(@dataBlock[256 & callerPointer], 512)
samplePosition := numberOfSamples
repeat (((((numberOfSamples * blockAlign) + 511) / 512) - 1) #> 0)
not callerPointer
repeat while(callerPointer == callePointer)
fat.readData(@dataBlock[256 & callerPointer], 512)
PUB DACEngineStart(leftPinNumber, rightPinNumber, initialVolume) '' 9 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Starts up the DAC driver running on a cog.
'' //
'' // Returns true on success or false.
'' //
'' // LeftPinNumber - Pin to use to play the left channel audio. -1 to disable.
'' // RightPinNumber - Pin to use to play the right channel audio. -1 to disable.
'' // InitialVolume - Initial volume for the left and right audio channels. Between 0 and 100. 0 mutes.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DACEngineStop
if(chipver == 1)
clocksPerSample := clkfreq
rightVolume := leftVolume := (((initialVolume <# 100) #> 0) * constant($1_00_00 / 100))
leftCounterSetup := ((leftPinNumber & $1F) + constant(110 << 26))
rightCounterSetup := ((rightPinNumber & $1F) + constant(110 << 26))
outputMask := (((leftPinNumber <> -1) & (|<leftPinNumber)) | ((rightPinNumber <> -1) & (|<rightPinNumber)))
leftValueAddress := @leftValue
rightValueAddress := @rightValue
samplePositionAddress := @samplePosition
dataBlockAddress := @dataBlock
callePointerAddress := @callePointer
numberOfChannelsAddress := @numberOfChannels
bitsPerSampleAddress := @bitsPerSample
leftVolumeAddress := @leftVolume
rightVolumeAddress := @rightVolume
stopedOrStartedAddress := @stopedOrStarted
beginOrEndAddress := @beginOrEnd
ditherOutLeftAddress := @ditherLeft
ditherOutRightAddress := @ditherRight
cogIdentification := cognew(@initialization, @clocksPerSample)
result or= ++cogIdentification
PUB DACEngineStop '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Shuts down the DAC driver running on a cog.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(cogIdentification)
cogstop(-1 + cogIdentification~)
PUB DACDitherEngineStart(leftPinNumber, rightPinNumber, ditherLevel) '' 9 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Starts up the DAC dither driver running on a cog.
'' //
'' // The "DACEngineStart" method starts the regular non-dithering audio driver. If the audio quality is acceptable using it
'' // then the special dithering audio driver is not needed. If the audio quality is not acceptable then use the dither engine
'' // to eliminate both quantization noise from delta-modulation and pico-second jitter noise from on-chip crosstalk between
'' // nearby pins. Normally, these two noise sources generate distracting buzzes, whines, and hash, but dithering removes them
'' // in exchange for lower-level white noise which does not draw attention. The dither level can be adjusted - the further
'' // you get from COG0, the more dither you need. The special dither audio driver will use another cog in addition to the
'' // cog used by the regular non-dithering audio driver. Both audio drivers can output to different audio pins to produce
'' // a dithered audio source and non-dithered audio source. To produce only a dithered audio source disable the left and
'' // right audio channel pins in the regular non-dithering audio driver by passing -1 as the left and right pin numbers. If
'' // only a non-dithered audio source is required do not call the "DACDitherEngineStart" method - this saves a cog.
'' //
'' // Returns true on success or false.
'' //
'' // LeftPinNumber - Pin to use to play the left channel audio. -1 to disable.
'' // RightPinNumber - Pin to use to play the right channel audio. -1 to disable.
'' // DitherLevel - Dither level for the left and right audio channels. 0 = Most Dither ... 31 = Least Dither.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DACDitherEngineStop
if(chipver == 1)
ditherLeftCounterSetup := ((leftPinNumber & $1F) + constant(110 << 26))
ditherRightCounterSetup := ((rightPinNumber & $1F) + constant(110 << 26))
ditherOutputMask := (((leftPinNumber <> -1) & (|<leftPinNumber)) | ((rightPinNumber <> -1) & (|<rightPinNumber)))
leftDitherShift := rightDitherShift := (ditherLevel & $1F)
ditherLeftAddress := @ditherLeft
ditherRightAddress := @ditherRight
ditherCogIdentification := cognew(@ditherInitialization, 0)
result or= ++ditherCogIdentification
PUB DACDitherEngineStop '' 3 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Shuts down the DAC dither driver running on a cog.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(ditherCogIdentification)
cogstop(-1 + ditherCogIdentification~)
PUB FATEngineStart(DOPin, CLKPin, DIPin, CSPin, WPPin, CDPin, RTCReserved1, RTCReserved2, RTCReserved3) '' 18 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Starts up the SDC driver running on a cog and checks out a lock for the driver.
'' //
'' // This method should only be called once for any number of included versions of this object.
'' //
'' // This method causes all included versions of this object to need re-mounting when called.
'' //
'' // Returns true on success or false.
'' //
'' // DOPin - The SPI data out pin from the SD card. Between 0 and 31.
'' // CLKPin - The SPI clock pin from the SD card. Between 0 and 31.
'' // DIPin - The SPI data in pin from the SD card. Between 0 and 31.
'' // CSPin - The SPI chip select pin from the SD card. Between 0 and 31.
'' // WPPin - The SPI write protect pin from the SD card holder. Between 0 and 31. -1 if not installed.
'' // CDPin - The SPI write protect pin from the SD card holder. Between 0 and 31. -1 if not installed.
'' // RTCReserved1 - Reserved parameter 1 for RTC compatible driver versions. Pass -1.
'' // RTCReserved2 - Reserved parameter 2 for RTC compatible driver versions. Pass -1.
'' // RTCReserved3 - Reserved parameter 3 for RTC compatible driver versions. Pass -1.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return fat.FATEngineStart(DOPin, CLKPin, DIPin, CSPin, WPPin, CDPin, RTCReserved1, RTCReserved2, RTCReserved3)
PUB FATEngineStop '' 6 Stack Longs
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
'' // Shuts down the SDC driver running on a cog and returns the lock used by the driver.
'' //
'' // This method should only be called once for any number of included versions of this object.
'' //
'' // This method causes all included versions of this object to need re-mounting when called.
'' ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fat.FATEngineStop
DAT
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' DAC Driver
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
org 0
' //////////////////////Initialization/////////////////////////////////////////////////////////////////////////////////////////
initialization mov ctra, leftCounterSetup ' Setup counter modes to duty cycle mode.
mov ctrb, rightCounterSetup '
mov frqa, longAdjust '
mov frqb, longAdjust '
mov dira, outputMask '
mov playerPointer, dataBlockAddress '
rdlong timeCounter, par ' Setup timing.
add timeCounter, cnt '
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Player
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
outerLoop rdlong buffer, samplePositionAddress wz ' Enable playback playback given samples.
muxnz playerMode, #4 '
rdword buffer, numberOfChannelsAddress ' Setup number of channels.
cmp buffer, #1 wz '
muxz playerMode, #1 '
rdword buffer, bitsPerSampleAddress ' Setup bits per channel.
cmp buffer, #8 wz '
muxz playerMode, #2 '
mov counter, #128 ' Setup loop counter.
test playerMode, #1 wc '
if_c shl counter, #1 '
test playerMode, #2 wc '
if_c shl counter, #1 '
' //////////////////////Inner Loop/////////////////////////////////////////////////////////////////////////////////////////////
innerLoop rdlong buffer, par ' Wait until next sample output period.
waitcnt timeCounter, buffer '
rdbyte buffer, stopedOrStartedAddress wz ' If stopped loop continously.
if_nz mov frqa, longAdjust '
if_nz mov frqb, longAdjust '
if_nz jmp #innerLoop '
movs signedLongOutput, #leftValueAddress ' Get and output value.
movs multiplicand, #leftVolumeAddress '
movs unsignedLongOutput, #ditherOutLeftAddress '
call #decode '
mov frqa, sampleBuffer '
test playerMode, #1 wc ' Check number of channels.
test playerMode, #2 wz '
if_c_and_nz sub playerPointer, #1 '
if_c_and_z sub playerPointer, #2 '
movs signedLongOutput, #rightValueAddress ' Get and output value.
movs multiplicand, #rightVolumeAddress '
movs unsignedLongOutput, #ditherOutRightAddress '
call #decode '
mov frqb, sampleBuffer '
rdlong buffer, samplePositionAddress ' Decrement position.
cmpsub buffer, #1 wc, wz '
if_c wrlong buffer, samplePositionAddress '
if_z andn playerMode, #4 ' Disable playback given samples.
test playerMode, #4 wc ' Playback begun.
if_c mov buffer, #$FF '
if_c_and_nz wrbyte buffer, beginOrEndAddress '
if_z wrbyte buffer, beginOrEndAddress ' Playback be done.
djnz counter, #innerLoop ' Loop.
' //////////////////////Outer Loop/////////////////////////////////////////////////////////////////////////////////////////////
rdword buffer, callePointerAddress wz ' Switch data block pointer.
sumz buffer, #1 '
wrword buffer, callePointerAddress '
if_nz mov playerPointer, dataBlockAddress '
jmp #outerLoop ' Loop.
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Decode Value
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
decode test playerMode, #2 wc ' Read data depending on size.
if_c rdbyte multiplyBuffer, playerPointer ' Read a byte or a word.
if_c add playerPointer, #1 '
if_nc rdword multiplyBuffer, playerPointer '
if_nc add playerPointer, #2 '
if_c sub multiplyBuffer, #128 ' Sign extend.
if_c shl multiplyBuffer, #24 '
if_nc shl multiplyBuffer, #16 '
sar multiplyBuffer, #16 '
test playerMode, #4 wz ' Zero playback given samples.
if_z mov multiplyBuffer, #0 '
signedLongOutput wrlong multiplyBuffer, 0 ' Update main memory.
multiplicand rdword multiplyCounter, 0 ' Setup inputs.
mov sampleBuffer, #0 '
abs multiplyBuffer, multiplyBuffer wc ' Backup sign.
rcr sampleBuffer, #1 wz, nr '
multiplyLoop shr multiplyCounter, #1 wc ' Preform multiplication.
if_c add sampleBuffer, multiplyBuffer '
shl multiplyBuffer, #1 '
tjnz multiplyCounter, #multiplyLoop '
negnz sampleBuffer, sampleBuffer ' Restore sign and center value.
unsignedLongOutput wrlong sampleBuffer, 0 '
add sampleBuffer, longAdjust '
decode_ret ret ' Return.
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Data
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
longAdjust long $80_00_00_00 ' Centers output.
' //////////////////////Configuration Settings/////////////////////////////////////////////////////////////////////////////////
leftCounterSetup long 0
rightCounterSetup long 0
outputMask long 0
' //////////////////////Addresses//////////////////////////////////////////////////////////////////////////////////////////////
leftValueAddress long 0
rightValueAddress long 0
samplePositionAddress long 0
dataBlockAddress long 0
callePointerAddress long 0
numberOfChannelsAddress long 0
bitsPerSampleAddress long 0
leftVolumeAddress long 0
rightVolumeAddress long 0
stopedOrStartedAddress long 0
beginOrEndAddress long 0
ditherOutLeftAddress long 0
ditherOutRightAddress long 0
' //////////////////////Run Time Variables/////////////////////////////////////////////////////////////////////////////////////
buffer res 1
counter res 1
playerPointer res 1
playerMode res 1
sampleBuffer res 1
timeCounter res 1
multiplyBuffer res 1
multiplyCounter res 1
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fit 496
DAT
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' DAC Dither Driver
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
org 0
' //////////////////////Initialization/////////////////////////////////////////////////////////////////////////////////////////
ditherInitialization mov ctra, ditherLeftCounterSetup ' Setup counter modes to duty cycle mode.
mov ctrb, ditherRightCounterSetup '
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Dither
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ditherLoop test leftLFSR, leftTaps wc ' Iterate left dither source
rcl leftLFSR, #1 '
test rightLFSR, rightTaps wc ' Iterate right dither source
rcl rightLFSR, #1 '
rdlong ditherLBuffer, ditherLeftAddress ' Read left source and shift dither.
mov ditherLCounter, leftLFSR '
sar ditherLCounter, leftDitherShift '
rdlong ditherRBuffer, ditherRightAddress ' Read right source and shift dither.
mov ditherRCounter, rightLFSR '
sar ditherRCounter, rightDitherShift '
add ditherLBuffer, ditherLCounter ' Apply dither.
add ditherLBuffer, ditherAdjust '
mov frqa, ditherLBuffer ' Output.
add ditherRBuffer, ditherRCounter ' Apply dither.
add ditherRBuffer, ditherAdjust '
mov frqb, ditherRBuffer ' Output.
mov dira, ditherOutputMask ' Repeat.
jmp #ditherLoop '
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Data
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ditherAdjust long $80_00_00_00 ' Prevents poping.
leftTaps long $A4_00_00_80 ' Left LFSR taps.
rightTaps long $80_A0_10_00 ' Right LFSR taps.
leftLFSR long 1 ' Initial value.
rightLFSR long 1 ' Initial value.
' //////////////////////Configuration Settings/////////////////////////////////////////////////////////////////////////////////
ditherLeftCounterSetup long 0
ditherRightCounterSetup long 0
ditherOutputMask long 0
leftDitherShift long 0
rightDitherShift long 0
' //////////////////////Addresses//////////////////////////////////////////////////////////////////////////////////////////////
ditherLeftAddress long 0
ditherRightAddress long 0
' //////////////////////Run Time Variables/////////////////////////////////////////////////////////////////////////////////////
ditherLBuffer res 1
ditherLCounter res 1
ditherRBuffer res 1
ditherRCounter res 1
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fit 496
{{
and place this were ever you decided to play chimes -