arduino_midi_player/Midi/music-box-pc-master/WaveTableSynthesizer/Synth_rv32.S
2025-03-24 14:30:56 +08:00

327 lines
7.7 KiB
ArmAsm

#include "riscv_encoding.h"
.section .data
lastLimiterGain:
.word 256
.section .text
.global SynthAsm
.global GenDecayEnvlopeAsm
.global NoteOnAsm
// typedef struct _SoundUnit
// {
// uint32_t wavetablePos;
// uint32_t waveTableAddress;
// uint32_t waveTableLen;
// uint32_t waveTableLoopLen;
// uint32_t waveTableAttackLen;
// uint32_t envelopePos;
// uint32_t increment;
// int32_t val;
// int32_t sampleVal;
// uint32_t envelopeLevel;
// }SoundUnit;
// typedef struct _Synthesizer
// {
// SoundUnit SoundUnitList[POLY_NUM];
// int32_t mixOut;
// uint32_t lastSoundUnit;
// }Synthesizer;
.equ pWavetablePos , 0
.equ pWaveTableAddress , 4
.equ pWaveTableLen , 8
.equ pWaveTableLoopLen , 12
.equ pWaveTableAttackLen , 16
.equ pEnvelopePos ,20
.equ pIncrement , 24
.equ pVal , 28
.equ pSampleVal , 32
.equ pEnvelopeLevel , 36
.equ SoundUnitSize,40
.equ ENVELOP_LEN,256
.equ POLY_NUM,32
.equ pMixOut,SoundUnitSize*POLY_NUM
.equ pLastSoundUnit,pMixOut+4
.equ WAVETABLE_CELESTA_C5_LEN,2608
.equ WAVETABLE_CELESTA_C5_ATTACK_LEN,1998
.equ WAVETABLE_CELESTA_C5_LOOP_LEN,610
.equ WAVETABLE_CELESTA_C6_LEN, 1358
.equ WAVETABLE_CELESTA_C6_ATTACK_LEN, 838
.equ WAVETABLE_CELESTA_C6_LOOP_LEN, 520
.equ PWM_OUT1,0x40000438
.equ PWM_OUT2,0x4000043C
#define SPI1 (0x40000000U + 0x00003800U) /*!< SPI base address */
#define SPI_DATA (SPI1 + 0x0CU) /*!< SPI data register */
#define APB2_BUS_BASE 0x40010000U /*!< apb2 base address */
#define GPIO_BASE (APB2_BUS_BASE + 0x00000800U) /*!< GPIO base address */
#define GPIOA (GPIO_BASE + 0x00000000U)
#define GPIOA_BOP (GPIOA + 0x10U) /*!< GPIO port bit operation register */
#define GPIOA_BC (GPIOA + 0x14U) /*!< GPIO bit clear register */
.func SynthAsm
SynthAsm:
// push {r1-r2,r4-r7,lr}
#define pSoundUnit t1
#define loopIndex t2
#define mixOut t3
li t5,GPIOA_BOP
li t4,(0x01<<2)|(0x01<<4)
sw t4,(t5)
li loopIndex, POLY_NUM
mv mixOut, x0
mv pSoundUnit,a0
loopSynth:
lw t4,pEnvelopeLevel(pSoundUnit)
beqz t4,loopSynthEnd
lw t5,pWaveTableAddress(pSoundUnit)
lw t6,pWavetablePos(pSoundUnit)
srli t6,t6,8 //wavetablePos /= 256
slli t6,t6,1 //wavetablePos *= 2
add t6,t5,t6 // Load signed 16bit sample to t6
lh t6,(t6) //
sw t6,pSampleVal(pSoundUnit)
mul t4,t6,t4 //sample*envelope
// srai t4,t4,8
sw t4,pVal(pSoundUnit)
add mixOut,t4,mixOut //mixOut+=sample*envelope
lw t6,pWavetablePos(pSoundUnit)
lw t5,pIncrement(pSoundUnit)
add t6,t5,t6
lw t5,pWaveTableLen(pSoundUnit)
slli t5,t5,8 //pWaveTableLen*=256
bgeu t5,t6,wavePosUpdateEnd //bgeu:">="
lw t5,pWaveTableLoopLen(pSoundUnit)
slli t5,t5,8 //waveTableLoopLen*=256
sub t6,t6,t5
wavePosUpdateEnd:
sw t6,pWavetablePos(pSoundUnit)
loopSynthEnd:
addi loopIndex,loopIndex,-1 // set n = n-1
addi pSoundUnit,pSoundUnit,SoundUnitSize
bnez loopIndex,loopSynth
srai mixOut,mixOut,8 // mixOut/=255 ( envelope)
li t5,150
mul mixOut,t5,mixOut //pre vol
srai mixOut,mixOut,8
//j limiterEnd
#define FIX_POINT_WEIGHT 256
#define GAIN_1_FIX FIX_POINT_WEIGHT
#define TIME_CONST_ATTACK_FIX 0
#define TIME_CONST_RELEASE_FIX 230
#define THRESHOLD (32768-1) // 2^16-1
#define THRESHOLD_FIX THRESHOLD*FIX_POINT_WEIGHT
beqz mixOut,limiterEnd
li t5,THRESHOLD
li t6,GAIN_1_FIX
mv t4,mixOut
bgtz mixOut,calcGainStart
neg t4,mixOut
calcGainStart:
bleu t4,t5,calcGainEnd
li t5,THRESHOLD_FIX
divu t5,t5,t4
mv t6,t5
mv t1,t6
calcGainEnd:
la t5,lastLimiterGain
lw t5,(t5)
bleu t5,t6,releaseSmooth
attackSmooth:
li t4,GAIN_1_FIX-TIME_CONST_ATTACK_FIX
mul t6,t4,t6
li t4,TIME_CONST_ATTACK_FIX
mul t5,t4,t5
add t6,t5,t6
srai t6,t6,8
li t5,GPIOA_BC
li t4,0x01<<1
sw t4,(t5)
j smoothEnd
releaseSmooth:
li t4,GAIN_1_FIX-TIME_CONST_RELEASE_FIX
mul t6,t4,t6
li t4,TIME_CONST_RELEASE_FIX
mul t5,t4,t5
add t6,t5,t6
srai t6,t6,8
li t5,GPIOA_BOP
li t4,0x01<<1
sw t4,(t5)
smoothEnd:
bleu t6,t1,extraGainCorrectEnd
mv t6,t1
extraGainCorrectEnd:
la t5,lastLimiterGain
sw t6,(t5)
mul mixOut,t6,mixOut
srai mixOut,mixOut,8
limiterEnd:
// mixOut /=1<<6, 2^(10-1)<= mixOut <=2^(10-1)-1
//srai mixOut,mixOut,(8+1)
li t5,-32767
bge mixOut,t5,saturateLowerBoundSatisfied
mv mixOut,t5
saturateLowerBoundSatisfied:
li t5,32767
ble mixOut,t5,saturateEnd
mv mixOut,t5
saturateEnd:
// mixOut: [-512,511] -> [0,1023]
//add mixOut,mixOut,t5
//li t5,PWM_OUT1
//sh mixOut,(t5)
//li t5,PWM_OUT2
//sh mixOut,(t5)
li t5,SPI_DATA
sh mixOut,(t5)
mv pSoundUnit,a0
sw mixOut,pMixOut(pSoundUnit)
li t5,GPIOA_BC
li t4,(0x01<<2)|(0x01<<4)
sw t4,(t5)
ret
.endfunc
.func GenDecayEnvlopeAsm
GenDecayEnvlopeAsm:
//pSoundUnitGenEnv .req r0
//loopIndexGenEnv .req r4
//push {r1-r2,r4-r7,lr}
#define pSoundUnitGenEnv t1
#define loopIndexGenEnv t2
mv pSoundUnitGenEnv,a0
li loopIndexGenEnv,POLY_NUM
loopGenDecayEnvlope:
// void GenDecayEnvlopeC(Synthesizer* synth)
// {
// SoundUnit* soundUnits = synth->SoundUnitList//
// for (uint32_t i = 0// i < POLY_NUM// i++)
// {
// if((soundUnits[i].wavetablePos>>8) >=soundUnits[i].waveTableAttackLen &&
// soundUnits[i].envelopePos <sizeof(EnvelopeTable)-1)
// {
// soundUnits[i].envelopeLevel = EnvelopeTable[soundUnits[i].envelopePos]//
// soundUnits[i].envelopePos += 1//
// }
// }
// }
lw t5,pWavetablePos(pSoundUnitGenEnv)
lw t6,pWaveTableAttackLen(pSoundUnitGenEnv)
slli t6,t6,8
bltu t5,t6,conditionEnd // blt:"<"
lw t5,pEnvelopePos(pSoundUnitGenEnv)
li t6,(ENVELOP_LEN-1)
bgeu t5,t6,conditionEnd // bhs Higher or same (unsigned >= )
la t6,EnvelopeTable
add t6,t5,t6
lbu t6,(t6) // Load envelope to r6
sw t6,pEnvelopeLevel(pSoundUnitGenEnv)
addi t5,t5,1
sw t5,pEnvelopePos(pSoundUnitGenEnv)
conditionEnd:
addi loopIndexGenEnv,loopIndexGenEnv,-1 // set n = n-1
addi pSoundUnitGenEnv,pSoundUnitGenEnv,SoundUnitSize
bnez loopIndexGenEnv,loopGenDecayEnvlope
//pop {r1-r2,r4-r7,pc}
ret
.endfunc
.func NoteOnAsm
NoteOnAsm:
#define pSynth t4
#define note a1
//push {r1-r2,r4-r7,lr}
mv pSynth,a0
// void NoteOnC(Synthesizer* synth,uint8_t note)
// {
// uint8_t lastSoundUnit = synth->lastSoundUnit//
// SoundUnit* soundUnits = synth->SoundUnitList//
// //disable_interrupts()//
// soundUnits[lastSoundUnit].increment = WaveTable_Celesta_C5_Increment[note&0x7F]//
// soundUnits[lastSoundUnit].wavetablePos = 0//
// soundUnits[lastSoundUnit].waveTableAddress = (uint32_t)WaveTable_Celesta_C5//
// soundUnits[lastSoundUnit].waveTableLen = WAVETABLE_CELESTA_C5_LEN//
// soundUnits[lastSoundUnit].waveTableLoopLen = WAVETABLE_CELESTA_C5_LOOP_LEN//
// soundUnits[lastSoundUnit].waveTableAttackLen = WAVETABLE_CELESTA_C5_ATTACK_LEN//
// //enable_interrupts()//
// lastSoundUnit++//
// if (lastSoundUnit== POLY_NUM)
// lastSoundUnit = 0//
// synth->lastSoundUnit=lastSoundUnit//
// }
lw t5,pLastSoundUnit(pSynth)
li t6,SoundUnitSize
mul t5,t5,t6
add pSynth,pSynth,t5
li t5,0x7F
and note,note,t5
slli note,note,1
la t5,WaveTable_Celesta_C5_Increment
add t5,t5,note
lhu t5,(t5)
csrc CSR_MSTATUS, MSTATUS_MIE // Disable all interrupt
sw t5,pIncrement(pSynth)
mv t5,x0
sw t5,pWavetablePos(pSynth)
la t5,WaveTable_Celesta_C5
sw t5,pWaveTableAddress(pSynth)
li t5,WAVETABLE_CELESTA_C5_LEN
sw t5,pWaveTableLen(pSynth)
li t5,WAVETABLE_CELESTA_C5_LOOP_LEN
sw t5,pWaveTableLoopLen(pSynth)
li t5,WAVETABLE_CELESTA_C5_ATTACK_LEN
sw t5,pWaveTableAttackLen(pSynth)
sw x0,pEnvelopePos(pSynth)
li t5,255
sw t5,pEnvelopeLevel(pSynth)
csrs CSR_MSTATUS, MSTATUS_MIE // Enable all interrupt
mv pSynth,a0
lw t5,pLastSoundUnit(pSynth)
addi t5,t5,1
addi t6,t5,-POLY_NUM
bnez t6,updateLastSoundUnitEnd
mv t5,x0
updateLastSoundUnitEnd:
sw t5,pLastSoundUnit(pSynth)
//pop {r1-r2,r4-r7,pc}
ret
.endfunc