tim Rowledge uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-tpr.45.mcz ==================== Summary ==================== Name: Sound-tpr.45 Author: tpr Time: 13 November 2015, 3:50:17.879 pm UUID: 257002b4-8961-45b2-86d2-9b8e1f85cd1f Ancestors: Sound-tpr.44 Sounds changes ported across from Scratch work; you really don't want an error raising prim call inside a critical block if possible. =============== Diff against Sound-topa.43 =============== Item was added: + ----- Method: Envelope>>computeSustainValueAtMSecs: (in category 'applying') ----- + computeSustainValueAtMSecs: mSecs + "Return the value of this envelope at the given number of milliseconds from its onset. Return zero for times outside the time range of this envelope." + "Note: Unlike the private method incrementalComputeValueAtMSecs:, this method does is not increment. Thus it is slower, but it doesn't depend on being called sequentially at fixed time intervals. + Note: this is the same as computeValueAtMSecs: apart from removing the first section that requires loopEndMSecs t obe nil; this appears to cause a problem when a sound in playing and is stopped whilst the #computeSlopeAtMSecs: method is run inside the SoundPlayer loop" + + | t i | + mSecs < 0 ifTrue: [^ 0.0]. + + mSecs < loopStartMSecs ifTrue: [ "attack phase" + i := self indexOfPointAfterMSecs: mSecs startingAt: 1. + i = 1 ifTrue: [^ (points at: 1) y * scale]. + ^ self interpolate: mSecs between: (points at: i - 1) and: (points at: i)]. + + "sustain phase" + loopMSecs = 0 ifTrue: [^ (points at: loopEndIndex) y * scale]. "looping on a single point" + t := loopStartMSecs + ((mSecs - loopStartMSecs) \\ loopMSecs). + i := self indexOfPointAfterMSecs: t startingAt: loopStartIndex. + + ^ self interpolate: t between: (points at: i - 1) and: (points at: i) + ! Item was removed: - ----- Method: Envelope>>computeValueAtMSecs: (in category 'applying') ----- - computeValueAtMSecs: mSecs - "Return the value of this envelope at the given number of milliseconds from its onset. Return zero for times outside the time range of this envelope." - "Note: Unlike the private method incrementalComputeValueAtMSecs:, this method does is not increment. Thus it is slower, but it doesn't depend on being called sequentially at fixed time intervals." - - | t i | - mSecs < 0 ifTrue: [^ 0.0]. - - ((loopEndMSecs ~~ nil) and: [mSecs >= loopEndMSecs]) ifTrue: [ "decay phase" - t := (points at: loopEndIndex) x + (mSecs - loopEndMSecs). - i := self indexOfPointAfterMSecs: t startingAt: loopEndIndex. - i == nil ifTrue: [^ 0.0]. "past end" - ^ (self interpolate: t between: (points at: i - 1) and: (points at: i)) * decayScale]. - - mSecs < loopStartMSecs ifTrue: [ "attack phase" - i := self indexOfPointAfterMSecs: mSecs startingAt: 1. - i = 1 ifTrue: [^ (points at: 1) y * scale]. - ^ self interpolate: mSecs between: (points at: i - 1) and: (points at: i)]. - - "sustain phase" - loopMSecs = 0 ifTrue: [^ (points at: loopEndIndex) y * scale]. "looping on a single point" - t := loopStartMSecs + ((mSecs - loopStartMSecs) \\ loopMSecs). - i := self indexOfPointAfterMSecs: t startingAt: loopStartIndex. - - ^ self interpolate: t between: (points at: i - 1) and: (points at: i) - ! Item was changed: ----- Method: Envelope>>sustainEnd: (in category 'applying') ----- sustainEnd: mSecs + "Set the ending time of the sustain phase of this envelope; the decay phase will start this + point. Typically derived from a note's duration. + Details: to avoid a sharp transient, the decay phase is scaled so that the beginning of the + decay matches the envelope's instantaneous value when the decay phase starts." - "Set the ending time of the sustain phase of this envelope; the decay phase will start this point. Typically derived from a note's duration." - "Details: to avoid a sharp transient, the decay phase is scaled so that the beginning of the decay matches the envelope's instantaneous value when the decay phase starts." | vIfSustaining firstVOfDecay | + loopEndMSecs := mSecs. "no longer set to nil in order to pretend to be sustaining" - loopEndMSecs := nil. "pretend to be sustaining" decayScale := 1.0. nextRecomputeTime := 0. + vIfSustaining := self computeSustainValueAtMSecs: mSecs. "get value at end of sustain phase" + "loopEndMSecs := mSecs. not required any more" - vIfSustaining := self computeValueAtMSecs: mSecs. "get value at end of sustain phase" - loopEndMSecs := mSecs. firstVOfDecay := (points at: loopEndIndex) y * scale. firstVOfDecay = 0.0 ifTrue: [decayScale := 1.0] ifFalse: [decayScale := vIfSustaining / firstVOfDecay]. ! Item was changed: ----- Method: SimpleMIDIPort>>midiCmd:channel:byte: (in category 'output') ----- midiCmd: cmd channel: channel byte: dataByte + "Immediately output the given MIDI command with the given channel and + argument byte to this MIDI port. Assume that the port is open." - "Immediately output the given MIDI command with the given channel and argument byte to this MIDI port. Assume that the port is open." accessSema critical: [ + self primMIDIWriteNoErrorPort: portNumber - self primMIDIWritePort: portNumber from: (ByteArray with: (cmd bitOr: channel) with: dataByte) at: 0]. ! Item was changed: ----- Method: SimpleMIDIPort>>midiCmd:channel:byte:byte: (in category 'output') ----- midiCmd: cmd channel: channel byte: dataByte1 byte: dataByte2 + "Immediately output the given MIDI command with the given channel + and argument bytes to this MIDI port. Assume that the port is open." - "Immediately output the given MIDI command with the given channel and argument bytes to this MIDI port. Assume that the port is open." accessSema critical: [ + self primMIDIWriteNoErrorPort: portNumber - self primMIDIWritePort: portNumber from: (ByteArray with: (cmd bitOr: channel) with: dataByte1 with: dataByte2) at: 0]. ! |
Free forum by Nabble | Edit this page |