@@ -194,45 +194,86 @@ func playSong(eh *world.EntityHandle, song *Song) {
194194 }
195195 if notes , found := notesPerTick [tick ]; found {
196196 for _ , note := range notes {
197- inst := sound .Piano ()
198- if note .Instrument >= 0 && note .Instrument < len (instrumentSounds ) {
199- inst = instrumentSounds [note .Instrument ]
200- }
201- pitch := pitchKey (note .Key )
202- // For further enhancement: use velocity, custom pitch, and panning as needed.
203- /* fmt.Printf(
204- "Tick=%d Layer=%d Instr=%d Key=%d Pitch=%d Vel=%d Pan=%d\n",
205- note.Tick, note.Layer, note.Instrument, note.Key, pitch, note.Velocity, note.Panning,
206- ) */
207- playSoundSelf (eh , sound.Note {
208- Instrument : inst ,
209- Pitch : pitch ,
197+ _ = eh .ExecWorld (func (tx * world.Tx , ent world.Entity ) {
198+ pp , ok := ent .(* player.Player )
199+ if ! ok {
200+ return
201+ }
202+ pos := pp .Position ()
203+ instrument := "note.harp"
204+ if note .Instrument >= 0 && note .Instrument < len (instrumentSounds ) {
205+ switch note .Instrument {
206+ case 1 :
207+ instrument = "note.basedrum"
208+ case 2 :
209+ instrument = "note.snare"
210+ case 3 :
211+ instrument = "note.hat"
212+ case 4 :
213+ instrument = "note.bass"
214+ case 5 :
215+ instrument = "note.flute"
216+ case 6 :
217+ instrument = "note.bell"
218+ case 7 :
219+ instrument = "note.guitar"
220+ case 8 :
221+ instrument = "note.chime"
222+ case 9 :
223+ instrument = "note.xylophone"
224+ case 10 :
225+ instrument = "note.iron_xylophone"
226+ case 11 :
227+ instrument = "note.cow_bell"
228+ case 12 :
229+ instrument = "note.didgeridoo"
230+ case 13 :
231+ instrument = "note.bit"
232+ case 14 :
233+ instrument = "note.banjo"
234+ case 15 :
235+ instrument = "note.pling"
236+ }
237+ }
238+ pitch := Floatkey (note .Key )
239+ volume := FloatVel (note .Velocity )
240+ PacketPlaySound (pp , instrument , pitch , volume , pos )
210241 })
211242 }
212243 }
213244 }
214245}
215246
216- // playSoundSelf plays a sound only for the provided player entity (self).
217- func playSoundSelf (eh * world.EntityHandle , snd world.Sound ) {
218- _ = eh .ExecWorld (func (tx * world.Tx , ent world.Entity ) {
219- pp , ok := ent .(* player.Player )
220- if ! ok {
221- return
222- }
223- pos := pp .Position ()
224- tx .PlaySound (pos , snd )
225- })
226- }
227-
228- // pitchKey calculates the Bedrock note pitch index based on the NBS note key.
247+ // PitchKey calculates the Bedrock note pitch index based on the NBS note key.
229248// Bedrock's base is 33 (F#3).
230- func pitchKey (key int ) int {
249+ func PitchKey (key int ) int {
231250 base := 33 // F#3 is key 33 in Bedrock
232251 return key - base
233252}
234253
235- // Pow is a helper to call math.Pow.
254+ // Bedrock "note" starts at key 33 (F#3). Each +12 is one octave (double freq/float).
255+ //
256+ // F#3 = 0.5, F#4 = 1.0, F#5 = 2.0, etc.
257+ //
258+ // So, the formulat is: 0.5 * 2^((key-33)/12)
259+ func Floatkey (key int ) float32 {
260+ baseKey := 33
261+ return float32 (0.5 * math .Pow (2 , float64 (key - baseKey )/ 12 ))
262+ }
263+
264+ // FloatVel converts NBS/JSON note velocity (0-100) to Bedrock/Dragonfly volume [0.0, 1.0].
265+ // Values below or equal 0 are muted; above 100 are clamped to 1.0
266+ func FloatVel (val int ) float32 {
267+ if val <= 0 {
268+ return 0
269+ }
270+ if val >= 100 {
271+ return 1.0
272+ }
273+ return float32 (val ) / 100.0
274+ }
275+
276+ // Pow is a helper function alias for math.Pow (for convenience).
236277func Pow (base , exp float64 ) float64 {
237278 return math .Pow (base , exp )
238279}
0 commit comments