SoundMorphicUserInterface

AbstractMediaEventMorph
An abstract representation of media events to be placed in a PianoRollScoreMorph (or others as they are developed)
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
endTime
initialize
initialize the state of the receiver
CodecDemoMorph
A CodecDemoMorph is xxxxxxxxx.
Instance Variables
codecClassName: <Object>
codecClassName
- xxxxx
acceptDroppingMorph:event:
This message is sent when a morph is dropped onto a morph that has agreed to accept the dropped morph by responding 'true' to the wantsDroppedMorph:Event: message. This default implementation just adds the given morph to the receiver.
addCustomMenuItems:hand:
Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.
codecClassName:
defaultColor
answer the default color/fill style for the receiver
initialize
initialize the state of the receiver
selectCodec
wantsDroppedMorph:event:
Return true if the receiver wishes to accept the given morph, which is being dropped by a hand in response to the given event. Note that for a successful drop operation both parties need to agree. The symmetric check is done automatically via aMorph wantsToBeDroppedInto: self.
EnvelopeEditorMorph
An EnvelopeEditorMorph is xxxxxxxxx.
Instance Variables
denominator: <Object>
envelope: <Object>
graphArea: <Object>
hScale: <Object>
keyboard: <Object>
limitHandles: <Object>
limitXs: <Object>
limits: <Object>
line: <Object>
pixPerTick: <Object>
prevMouseDown: <Object>
sampleDuration: <Object>
showAllEnvelopes: <Object>
sound: <Object>
soundName: <Object>
vScale: <Object>
denominator
- xxxxx
envelope
- xxxxx
graphArea
- xxxxx
hScale
- xxxxx
keyboard
- xxxxx
limitHandles
- xxxxx
limitXs
- xxxxx
limits
- xxxxx
line
- xxxxx
pixPerTick
- xxxxx
prevMouseDown
- xxxxx
sampleDuration
- xxxxx
showAllEnvelopes
- xxxxx
sound
- xxxxx
soundName
- xxxxx
vScale
- xxxxx
acceptGraphPoint:at:
addControls
addCurves
Add the polyLine corresponding to the currently selected envelope,
and possibly all the others, too.
addCustomMenuItems:hand:
Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.
addEnvelopeNamed:
addHandlesIn:
addKeyboard
adjustScale:
buildGraphAreaIn:
buildScalesIn:
buildView
chooseDenominator:
chooseEnvelope:
chooseFrom:envelopeItem:
chooseFrom:soundItem:
chooseSound:
clickOn:evt:from:
clickOnLine:evt:envelope:
Reorder the arguments for existing event handlers
colorForEnvelope:
constrain:adjacentTo:in:
Return xVal, restricted between points adjacent to vertX
curveChoices
deletePoint:
If the point is a limit point, return false,
otherwise, delete the point at ix, and return true.
editEnvelope:
editNewSound
editSound:
editSoundNamed:
extent:
handleOffset:
This is the offset from position to the bottom vertex
initOnSound:title:
initialize
initialize the state of the receiver
insertPointAfter:
If there is not enough roon (in x) then return false.
Otherwise insert a point between ix and ix+1 and return true.
limitHandleMove:event:from:
index is the handle index = 1, 2 or 3
limitHandleMoveEvent:from:index:
Reorder the arguments for existing event handlers
maxTime
msFromX:
openOn:title:
playNothing
readFileNamed:
readFromDisk:
removeEnvelope
saveLibToDisk:
Save the library to disk
saveSound:
saveToDisk:
setDenominator:
soundBeingEdited
soundChoices
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
stepTime
Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.
valueFromY:
The convention is that envelope values are between 0.0 and 1.0
wantsRoundedCorners
Return true if the receiver wants its corners rounded
xFromMs:
yFromValue:
The convention is that envelope values are between 0.0 and 1.0
EnvelopeLineMorph
An EnvelopeLineMorph is xxxxxxxxx.
Instance Variables
editor: <Object>
editor
- xxxxx
defaultColor
answer the default color/fill style for the receiver
dragVertex:event:fromHandle:
dropVertex:event:fromHandle:
Leave vertex in new position. If dropped ontop another vertex delete this one.
Check for too few vertices before deleting. The alternative
is not pretty -wiz
newVertex:event:fromHandle:
Install a new vertex if there is room.
vertices:borderWidth:borderColor:
GraphMorph
I display a graph of numbers, normalized so the full range of values just fits my height. I support a movable cursor that can be dragged with the mouse.
Implementation notes: Some operations on me may be done at sound sampling rates (e.g. 11-44 thousand times/second). To allow such high bandwidth application, certain operations that change my appearance do not immediately report a damage rectangle. Instead, a flag is set indicating that my display needs to refreshed and a step method reports the damage rectangle if that flag is set. Also, I cache a bitmap of my graph to allow the cursor to be moved without redrawing the graph.
GraphMorph new openInWorld
appendValue:
centerCursor
Scroll so that the cursor is as close as possible to the center of my window.
clear
color:
Set the receiver's color. Directly set the color if appropriate, else go by way of fillStyle
convertToCurrentVersion:refStream:
cursor
vacuous backstop in case it gets sent to a morph that doesn't know what to do with it
cursor:
vacuous backstop in case it gets sent to a morph that doesn't know what to do with it
cursorAtEnd
cursorColor
cursorColor:
cursorColorAtZeroCrossing
cursorColorAtZeroCrossings:
cursorWrapped:
data
data:
dataColor
dataColor:
defaultColor
answer the default color/fill style for the receiver
descriptionForPartsBin
drawCursorOn:
drawDataOn:
drawOn:
flushCachedForm
handlesMouseDown:
Do I want to receive mouseDown events (mouseDown:, mouseMove:, mouseUp:)?
initialize
initialize the state of the receiver
interpolatedValueAtCursor
keepIndexInView:
lastValue
lastValue:
layoutChanged
Fixed to always flush layout cache - finally tracked down
layout anomalies due to cached extents in layout
policies not being flushed, the previous (incorrect) assumption being
that it did not matter if layout was to be recomputed (fullBounds being nil).
Recomputing of the layout apparently does not flush so must be done here.
loadSineWave
loadSound:
loadSoundData:
mouseMove:
Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.
playOnce
reverse
startIndex
startIndex:
step
Make a deferred damage rectangle if I've changed. This allows applications to call methods that invalidate my display at high-bandwidth without paying the cost of doing the damage reporting on ever call; they can merely set hasChanged to true.
valueAtCursor
valueAtCursor:
InterimSoundMorph
An InterimSoundMorph is xxxxxxxxx.
Instance Variables
graphic: <Object>
sound: <Object>
graphic
- xxxxx
sound
- xxxxx
addGraphic
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
handlesMouseDown:
Do I want to receive mouseDown events (mouseDown:, mouseMove:, mouseUp:)?
initialize
initialize the state of the receiver
mouseDown:
Handle a mouse down event. The default response is to let my
eventHandler, if any, handle it.
sound
sound:
speakerGraphic
KeyboardMorphForInput
This class adds state and controls to the basic PianoKeyboardMorph so that notes of reliable duration can be keyed into a score without the need for a real keyboard.
To try this out, execute...
| n score | n _ 3.
score _ (MIDIScore new tracks: ((1 to: n) collect: [:i | Array new]);
trackInfo: ((1 to: n) collect: [:i | 'Instrument' , i printString]);
tempoMap: nil; ticksPerQuarterNote: 96).
ScorePlayerMorph openOn: score title: 'empty score'
Then open a pianoRoll and, from that, open a keyboard. The rule is that the keyboard will append after the current selection. If the current selection is muted or nil, then input will go to the end of the first non-muted track.
addRecordingControls
Add chord, rest and delete buttons
articulation:onOff:
artic = eg, #legato, #normal, #staccato.
backspaceNote
buildChord:
deleteNotes
durMod:onOff:
durMod = eg, #dotted, #normal, #triplets, #quints
duration:onOff:
denom = eg, 1, 2, 4, 8, 16
emitRest
All this selection logic should be shared with mouseDown...
fullDuration
initialize
initialize the state of the receiver
mouseDownPitch:event:noteMorph:
mouseUpPitch:event:noteMorph:
noteDuration
pianoRoll:
soundForEvent:inTrack:
velocity
MIDIControllerMorph
A MIDIControllerMorph is xxxxxxxxx.
Instance Variables
channel: <Object>
controller: <Object>
lastValue: <Object>
midiPort: <Object>
channel
- xxxxx
controller
- xxxxx
lastValue
- xxxxx
midiPort
- xxxxx
addCustomMenuItems:hand:
Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.
channel
channel:
controller
controller:
controllerList
Answer a list of controller name, number pairs to be used in the menu.
controllerName:
Answer a name for the given controller. If no name is available, use the form 'CC5' (CC is short for 'continuous controller').
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
initialize
initialize the state of the receiver
midiPort
midiPort:
newSliderValue:
Send a control command out the MIDI port.
setChannel:
setController:
updateLabel
MIDIPianoKeyboardMorph
I implement a piano keyboard that can be played with the mouse. I can output to a MIDI port, if MIDI is supported on this platform. I can also spawn controllers for other MIDI parameters, such as pitch bend.
addCustomMenuItems:hand:
Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.
closeMIDIPort
initialize
initialize the state of the receiver
makeMIDIController:
mouseDownPitch:event:noteMorph:
mouseUpPitch:event:noteMorph:
openMIDIPort
turnOffNote
turnOnNote:
MidiInputMorph
I am the user interface for a simple software MIDI synthesizer that is driven by external MIDI input. I come with controls for a single MIDI channel (channel 1), but allow channel controls for additional MIDI channels to be added by the user. The volume, pan, and instrument of each channel can be controlled independently.
addChannel
Add a set of controls for another channel. Prompt the user for the channel number.
addChannelControlsFor:
atChannel:from:selectInstrument:
channelNumAndMuteButtonFor:
closeMIDIPort
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
disableReverb:
initialize
initialize the state of the receiver
instrumentChoicesForChannel:
invokeMenu
Invoke a menu of additonal commands.
makeControls
makeRow
panAndVolControlsFor:
setMIDIPort
toggleOnOff
updateInstrumentsFromLibraryExcept:
The instrument library has been modified. Update my instruments with the new versions from the library. Use a single instrument prototype for all parts with the same name; this allows the envelope editor to edit all the parts by changing a single sound prototype.
PianoKeyboardMorph
A PianoKeyboardMorph is xxxxxxxxx.
Instance Variables
blackKeyColor: <Object>
nOctaves: <Object>
noteOffSelector: <Object>
noteOnSelector: <Object>
playingKeyColor: <Object>
soundPlaying: <Object>
soundPrototype: <Object>
target: <Object>
whiteKeyColor: <Object>
blackKeyColor
- xxxxx
nOctaves
- xxxxx
noteOffSelector
- xxxxx
noteOnSelector
- xxxxx
playingKeyColor
- xxxxx
soundPlaying
- xxxxx
soundPrototype
- xxxxx
target
- xxxxx
whiteKeyColor
- xxxxx
buildKeyboard
defaultColor
answer the default color/fill style for the receiver
descriptionForPartsBin
initialize
initialize the state of the receiver
mouseDownEvent:noteMorph:pitch:
Reorder the arguments for existing event handlers
mouseDownPitch:event:noteMorph:
mouseMoveEvent:noteMorph:pitch:
Reorder the arguments for existing event handlers
mouseMovePitch:event:noteMorph:
mouseUpEvent:noteMorph:pitch:
Reorder the arguments for existing event handlers
mouseUpPitch:event:noteMorph:
soundPrototype:
PianoRollScoreMorph
A PianoRollScoreMorph displays a score such as a MIDIScore, and will scroll through it tracking the progress of a ScorePlayerMorph (from which it is usually spawned).
timeScale is in pixels per score tick.
Currently the ambient track (for synchronizing thumbnails, eg) is treated specially here and in the score. This should be cleaned up by adding a trackType or something like it in the score.
acceptDroppingMorph:event:
In addition to placing this morph in the pianoRoll, add a corresponding
event to the score so that it will always appear when played, in addition
to possibly triggering other actions
addCustomMenuItems:hand:
Add morph-specific items to the given menu which was invoked by the given hand. This method provides is invoked both from the halo-menu and from the control-menu regimes.
addKeyboard
addNotes
Recompute the set of morphs that should be visible at the current scroll position.
appendEvent:fullDuration:
autoScrollForX:
Scroll by the amount x lies outside of my innerBounds. Return true if this happens.
beatLinesOnOff
beatsPerMeasure:
contractTime
copySelection
cutSelection
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
deleteSelection
drawMeasureLinesOn:
drawOn:
drawStaffOn:
expandTime
extent:
Force rebuild when re-sized.
fullBounds
Overridden to clip submorph hit detection to my bounds.
goToTime:
handlesMouseDown:
Do I want to receive mouseDown events (mouseDown:, mouseMove:, mouseUp:)?
initialize
initialize the state of the receiver
insertSelection
insertTransposed
invokeScoreMenu:
Invoke the score's edit menu.
isBlackKey:
Answer true if the given MIDI key corresponds to a black key on the piano keyboard.
layoutChanged
Override this to avoid propagating 'layoutChanged' when just adding/removing note objects.
measureLinesOnOff
midiKeyForY:
mouseDown:
Handle a mouse down event. The default response is to let my
eventHandler, if any, handle it.
mouseMove:
Handle a mouse move event. The default response is to let my eventHandler, if any, handle it.
mouseUp:
Handle a mouse up event. The default response is to let my eventHandler, if any, handle it.
moveCursorToTime:
movieClipPlayer
movieClipPlayer:
notePerBeat:
notesInRect:
on:
rebuildFromScore
Rebuild my submorphs from the score. This method should be invoked after changing the time scale, the color or visibility of a track, the extent of this morph, etc.
removedMorph:
Notify the receiver that aMorph was just removed from its children
score
scorePlayer
selection
Returns an array of 3 elements:
trackIndex
indexInTrack of first note
indexInTrack of last note
selection:
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
stepTime
Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.
tickTimeAtCursor
timeForX:
timeScale
timeSignature:over:
updateLowestNote
find the actual lowest note in the score
xForTime:
yForMidiKey:
RecordingControlsMorph
A RecordingControlsMorph is xxxxxxxxx.
Instance Variables
recordMeter: <Object>
recorder: <Object>
recordingStatusLight: <Object>
recordMeter
- xxxxx
recorder
- xxxxx
recordingStatusLight
- xxxxx
addButtonRows
addRecordLevelSlider
buttonName:action:
descriptionForPartsBin
done
initialize
initialize the state of the receiver
makeRecordMeter
makeSoundMorph
makeStatusLight
playback
The user hit the playback button
record
recorder
registerInFlapsRegistry
show
Show my samples in a WaveEditor.
startStepping
Make the level meter active when dropped into the world. Do nothing if already recording. Note that this will cause other recorders to stop recording...
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
stepTime
Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.
stop
Stop running my script. For ordinary morphs, this means stop stepping.
stopStepping
Turn off recording.
trim
Show my samples in a GraphMorph.
ScorePlayerMorph
A ScorePlayerMorph mediates between a score such as a MIDIScore, a PianoRollScoreMorph, and the actual SoundPlayer synthesizer.
It provides control over volume, tempo, instrumentation, and location in the score.
atTrack:from:selectInstrument:
closeMIDIPort
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
descriptionForPartsBin
fileReaderServicesForFile:suffix:
initialize
initialize the state of the receiver
instrumentChoicesForTrack:
invokeMenu
Invoke a menu of additonal functions for this ScorePlayer.
makeAPauseEvent:
makeControls
makeMIDIController:
makePianoRoll
Create a piano roll viewer for this score player.
makeRow
onMIDIFileNamed:
onScorePlayer:title:
openMIDIFile
Open a MIDI score and re-init controls...
openMIDIPort
openOn:title:
panAndVolControlsFor:
playMidiFile:
rateControl
rewind
saveAsAIFF
Create a stereo AIFF audio file with the result of performing my score.
saveAsSunAudio
Create a stereo Sun audio file with the result of performing my score.
saveAsWAV
Create a stereo WAV audio file with the result of performing my score.
scorePlayer
scrollControl
servicePlayMidiFile
services
setLogRate:
showResumeButtonInTheWorld
standaloneResumeButton
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
trackControlsFor:
trackNumAndMuteButtonFor:
unload
updateInstrumentsFromLibraryExcept:
The instrument library has been modified. Update my instruments with the new versions from the library. Use a single instrument prototype for all parts with the same name; this allows the envelope editor to edit all the parts by changing a single sound prototype.
volumeControl
wantsRoundedCorners
Return true if the receiver wants its corners rounded
SimpleSliderMorph
A SimpleSliderMorph is xxxxxxxxx.
Instance Variables
arguments: <Object>
maxVal: <Object>
minVal: <Object>
target: <Object>
truncate: <Object>
arguments
- xxxxx
maxVal
- xxxxx
minVal
- xxxxx
target
- xxxxx
truncate
- xxxxx
actionSelector
actionSelector:
addCustomMenuItems:hand:
To all the other Custom menu items add slider and targeting items.
addSliderMenuItems:hand:
Add items to set slider parameters
addTargetingMenuItems:hand:
Add targeting menu items
adjustToValue:
Adjust the position of this slider to correspond to the given value in the range minVal..maxVal.
arguments
arguments:
authoringPrototype
clearTarget
defaultNameStemForInstances
Answer a basis for names of default instances of the receiver. The default is to let the class specify, but certain instances will want to override. (PasteUpMorphs serving as Worlds come to mind
descendingString
descriptionForPartsBin
getScaledValue
initialize
initialize the state of the receiver
initializeToStandAlone
Set up the receiver, created by a #basicNew and now ready to be initialized, as a fully-formed morph suitable for providing a graphic for a parts bin surrogate, and, when such a parts-bin surrogate is clicked on, for attaching to the hand as a viable stand-alone morph. Because of historical precedent, #initialize has been expected to handle this burden, though a great number of morphs actually cannot stand alone. In any case, by default we call the historical #initialize, though unhappily, so that all existing morphs will work no worse than before when using this protocol.
isLikelyRecipientForMouseOverHalos
maxVal
maxVal:
minVal
minVal:
registerInFlapsRegistry
setActionSelector
setArguments
setLabel
setMaxVal
setMaxVal:
setMinVal
setMinVal:
setScaledValue:
setTarget:
setValue:
Update the target with this sliders new value.
target
target:
Morphs with targets will override. This backstop does nothing.
toggleDescending
toggleTruncate
truncate
truncate:
truncateString
unload
veryDeepFixupWith:
If target and arguments fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!
veryDeepInner:
Copy all of my instance variables. Some need to be not copied at all, but shared. Warning!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.
SoundDemoMorph
A SoundDemoMorph is xxxxxxxxx.
Instance Variables
soundColumn: <Object>
soundColumn
- xxxxx
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
initialize
initialize the state of the receiver
initializeSoundColumn
initialize the receiver's soundColumn
makeControls
playAll
playV1
playV2
playV3
setTimbreFromTile:
stopSound
SoundEventMorph
A SoundEventMorph is xxxxxxxxx.
Instance Variables
sound: <Object>
sound
- xxxxx
addMorphsTo:pianoRoll:eventTime:betweenTime:and:
a hack to allow for abitrary morphs to be dropped into piano roll
defaultColor
answer the default color/fill style for the receiver
encounteredAtTime:inScorePlayer:atIndex:inEventTrack:secsPerTick:
hack... since we are called from within the SoundPlayer loop, the Semaphore will
block attempts to play directly from here
initialize
initialize the state of the receiver
justDroppedIntoPianoRoll:event:
releaseCachedState
Release any state that can be recomputed on demand, such as the pixel values for a color gradient or the editor state for a TextMorph. This method may be called to save space when a morph becomes inaccessible. Implementations of this method should do 'super releaseCachedState'.
sound:
SoundLoopMorph
A SoundLoopMorph is xxxxxxxxx.
Instance Variables
controlIndex: <Object>
cursor: <Object>
samplesUntilNextControl: <Object>
seqSound: <Object>
controlIndex
- xxxxx
cursor
- xxxxx
samplesUntilNextControl
- xxxxx
seqSound
- xxxxx
addCursorMorph
buildSound
Build a compound sound for the next iteration of the loop.
controlRate
Answer the number of control changes per second.
defaultBorderWidth
answer the default border width for the receiver
defaultBounds
answer the default bounds for the receiver
defaultColor
answer the default color/fill style for the receiver
doControl
extent:
initialize
initialize the state of the receiver
mixSampleCount:into:startingAt:leftVol:rightVol:
Repeatedly play my sounds.
play
Play this sound to the sound ouput port in real time.
playSampleCount:into:startingAt:
Mixes the next count samples of this sound into the given buffer starting at the given index, updating the receiver's control parameters at periodic intervals.
positionCursor
reset
Reset my internal state for a replay.
samplesRemaining
samplingRate
Answer the sampling rate in samples per second.
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
stepTime
Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.
stop
Stop playing this sound.
wantsDroppedMorph:event:
Return true if the receiver wishes to accept the given morph, which is being dropped by a hand in response to the given event. Note that for a successful drop operation both parties need to agree. The symmetric check is done automatically via aMorph wantsToBeDroppedInto: self.
SoundMorph
Note: as of December 2000, this does not work. SoundMorph>>buildImage requires the sound to implement #volumeEnvelopeScaledTo: and as yet, no one does.
buildImage
initialize
initialize the state of the receiver
justDroppedInto:event:
This message is sent to a dropped morph after it has been dropped on -- and been accepted by -- a drop-sensitive morph
reset
sound
sound:
SoundSequencerMorph
A SoundSequencerMorph is xxxxxxxxx.
Instance Variables
controlPanel: <Object>
controlPanel
- xxxxx
initialize
initialize the state of the receiver
makeControlPanel
play
reset
stop
Stop running my script. For ordinary morphs, this means stop stepping.
SpeakerMorph
A SpeakerMorph is xxxxxxxxx.
Instance Variables
buffer: <Object>
bufferSize: <Object>
lastConePosition: <Object>
sound: <Object>
buffer
- xxxxx
bufferSize
- xxxxx
lastConePosition
- xxxxx
sound
- xxxxx
addGraphic
appendSample:
Append the given sample, a number between -100.0 and 100.0, to my buffer. Flush the buffer if it is full.
conePosition
conePosition:
defaultColor
answer the default color/fill style for the receiver
flushBuffer
initialize
initialize the state of the receiver
speakerGraphic
stopSound
SpectrumAnalyzerMorph
I am a tool for analyzing sound data from a microphone, CD, or other input source in real time. I have several display modes:
signal snapshots of the raw signal data as it arrives
spectrum frequency spectrum of the signal data as it arrives
sonogram scrolling plot of the frequency spectrum over time,
where the vertical axis is frequency, the horizontal
axis is time, and amount of energy at a given
frequency is shown as a grayscale value with
larger values being darker
To use this tool, be sure that you have selected the proper sound source using you host OS facilities. Set the desired sampling rate and FFT size (try 22050 samples/sec and an FFT size of 512) then click on the 'start' button. Use the slider to adjust the level so that the yellow level indicator peaks somewhere between the middle and the right edge at the maximum signal level.
Note that if the level meter peaks hit the right edge, you will get 'clipping', which creates a bunch of spurious high frequency noise in the frequency spectrum. If the display is set to 'signal' mode, you can actually see the tops and bottoms of the waveform being cut off when clipping occurs.
Many machines may not be able to perform spectrum analysis in real time, especially at higher sampling rates and larger FFT sizes. In both 'signal' and 'spectrum' modes, this tool will skip data to try to keep up with real time. However, in 'sonogram' mode it always processes all the data, even if it falls behind. This allows you to get a complete sonogram without dropouts even on a slower machine. However, as the sonogram display falls behind there will be a larger and larger time lag between when a sound is input and when it appears on the display.
The smaller the FFT size, the less frequency resolution you get. The lower the sampling rate, the less total frequency range you get. For an FFT size of N and a sampling rate of R, each of the N/2 'bins' of the frequency spectrum has a frequency resolution of R / N. For example, at a sampleing rate of 22050 samples/second, the total frequency range is 0 to 11025 Hz and an FFT of size 256 would divide this range into 128 bins (the output of an FFT of size N has N/2 bins), each of which covers a frequency band about 86 Hz wide.
To increase time resolution, increase the sampling rate and decrease the FFT size.
addButtonRow
addLevelSlider
buttonName:action:
defaultBorderWidth
answer the default border width for the receiver
delete
Turn off recording when this morph is deleted.
initialize
initialize the state of the receiver
invokeMenu
Invoke the settings menu.
makeLevelMeter
makeStatusLight
processBuffer:
Analyze one buffer of data.
removeAllDisplays
Remove all currently showing displays.
resetDisplay
Recreate my display after changing some parameter such as FFT size.
setDisplayType
Set the display type.
setFFTSize
Set the size of the FFT used for frequency analysis.
setSamplingRate
Set the sampling rate to be used for incoming sound data.
showSignal
Display the actual signal waveform.
showSonogram
Display a sonogram showing the frequency spectrum versus time.
showSpectrum
Display the frequency spectrum.
start
Start displaying sound data.
step
Update the record light, level meter, and display.
stepTime
Answer the desired time between steps in milliseconds. This default implementation requests that the 'step' method be called once every second.
stop
Stop displaying sound data.
stopStepping
Turn off recording.
updateDisplay
Update the display if any data is available.
WaveEditor
This tool was created to aid in the preparation of LoopedSampledSound objects. It includes support for finding good loop points with a little help from the user. Namely, the user must identify a good ending point for the loop (typically just before the decay phase begins) and identify one cycle of the waveform. After that, the "choose loop point" menu command can be invoked to search backwards to find and rank all possible loop starting points. Some experimentation is usually required to find a loop that "breaths" in a natural way.
This tool can also be used as a general viewer of numerical sequences of any kind, such as time-varying functions, FFT data, etc.
addControls
addLoopPointControls
autoCorrolationBetween:and:length:
Answer the cummulative error between the portions of my waveform starting at the given two indices and extending for the given length. The larger this error, the greater the difference between the two waveforms.
chooseLoopStart
data:
defaultBorderWidth
answer the default border width for the receiver
defaultColor
answer the default color/fill style for the receiver
descriptionForPartsBin
errorBetween:and:
Answer the cummulative error between the two sample arrays, which are assumed to be the same size.
findPossibleLoopStartsFrom:
Assume loopEnd is one sample before a zero-crossing.
fractionalLoopStartAt:
Answer the fractional index starting point near the given integral index that results in the closest match with the cycle following the loop end.
graph
initialize
initialize the state of the receiver
interpolatedWindowAt:width:
Return an array of N samples starting at the given index in my data.
invokeMenu
Invoke a menu of additonal functions for this WaveEditor.
jumpToLoopEnd
jumpToLoopStart
loopCycles
loopCycles:
loopEnd
loopEnd:
loopLength
loopLength:
loopStart
loopStart:
makeLoopedSampledSound
normalize:
Return a copy of the given sample array scaled to use the maximum 16-bit sample range. Remove any D.C. offset.
openOn:
perceivedFrequency
perceivedFrequency:
play
playAfterCursor
playBeforeCursor
playFrom:to:
playLoop
playTestNote
samplingRate
samplingRate:
saveInstrument
scrollTime:
setLoopEnd
setLoopStart
Assuming that the loop end and approximate frequency have been set, this method uses the current cursor position to determine the loop length and the number of cycles.
setOneCycle
Set the approximate frequency based on a single cycle specified by the user. To use this, first set the loop end, then place the cursor one full cycle before the loop end and invoke this method.
setUnlooped
Make this sound play straight through without looping.
setUnpitched
Make this instrument be unpitched and unlooped. Suitable for percussive sounds that should not be pitch-shifted when played. By convention, such sounds are played at a pitch of 100.0 to obtain their original pitch.
showEnvelope
Show an envelope wave constructed by collecting the maximum absolute value of the samples in fixed-size time windows of mSecsPerQuantum.
showFFTAtCursor
sound:
step
Do some periodic activity. Use startStepping/stopStepping to start and stop getting sent this message. The time between steps is specified by this morph's answer to the stepTime message. The generic version dispatches control to the player, if any. The nasty circumlocation about owner's transformation is necessitated by the flexing problem that the player remains in the properties dictionary both of the flex and the real morph. In the current architecture, only the top renderer's pointer to the player should actually be honored for the purpose of firing.
stretch:by:
Return an array consisting of the given samples \stretched in time by the given factor.
trimAfterCursor
trimBeforeCursor
zeroCrossingAfter:
Find the index of the next negative-to-non-negative transition at or after the current index. The result is the index, i, of a zero crossing such that the sample at i-1 is negative and the sample at i is zero or positive. Answer the index of the last sample if the end of the array is encountered before finding a zero crossing.