Smalltalk-80 Course - Utrecht, June, 1990 - Part 2 

		The HyperScore ToolKit

Outline
	Introduction
	MusicMagnitudes
	Events and EventLists
	EventList Hierarchies
	Voices, Event I/O
	Schedulers and Real-Time
	EventGenerators and Modifiers
	EventList Editors
	Signals and Functions
	Exercises


Introduction
	Background - ARA, (1983-4, LISP)
		SmallSong (events, event lists), DoubleTalk (Petri nets)
		HSTK 1-5 (three complete re-writes)
		HSTK 6.0 = Topaz--time for a new name

	Outline of HSTK
		Magnitude Models
		Event/EventList
		Voice drivers, Schedulers
		Middle-level structures--EGens, EMods
		UI Framework for Graphical Music Applications
		Built-in Applications
		Compositional Tools--algorithms, trees, etc.


MusicMagnitudes
	Review Smalltalk-80 Magnitudes
		The MusicMagnitude Assumption: all coercions within a species assumed, 
			but never assumed to be loss-less. Most general form used for
			mixed mode arithmetic within a species.

	New Abstract Concepts
		Nominal Magnitudes--symbolic name (e.g., 'mf' 'c#3') maps to number
			class table maps to some range (e.g., 0.0 to 1.0 or 0 to 127)

		Ratio Magnitudes--e.g., 3/2 of 'c'
			fractional value relative to some reference

		Ordinal Magnitudes--e.g., note1 'is sharper than' note2
			order-only, instance or class table stores comparisons

	Basic Models
		Abstract music magnitudes (Pitch, Amplitude, Duration) are creation-only 
			(i.e., the class has no instance methods and is never instantiated).
		It can create instances of concrete classes* based on type of value given.
		Concrete classes inherit representation models, not domain.
			
		Pitch class value: aValue
			"Answer a new instance of a pitch class."

			(aValue isMemberOf: SmallInteger)
					ifTrue: [^MIDIPitch new value: aValue].
			(aValue isMemberOf: Float)
					ifTrue: [^HertzPitch new value: aValue].
			(aValue isMemberOf: Fraction)
					ifTrue: [^RatioPitch new value: aValue].
			(aValue isKindOf: String)
					ifTrue: [^SymbolicPitch new value: aValue].
			^self error: 'Unknown pitch type'

	MusicMagnitude Hierarchy

	Magnitude ()--Smalltalk-80 System Class
		MusicMagnitude ('value' )--holds onto a value, implement arithmetic in
					terms of mostGeneral form of magnitude
			Amplitude ()--abstract classes, used for creation
			Duration ()
			Pitch ()
			PField ('name' )--named parameter field

			NominalMagnitude ('Table')--Class table for symbol lookup
				SymbolicLoudness ()--'ppp' <--> 'fff'
				SymbolicPitch ()--'a0' <--> 'g9'

			NumericalMagnitude ()--value is a number
				ConditionalDuration ()--e.g., until: []
				HertzPitch ()--261 Hz.
				MIDIPitch ()--Key 36
				MIDIVelocity ()--Vel. 100
				MSecondDuration ()--250 Ms.

			RatioMagnitude ('relative' )--fraction relative to another value
				RatioDuration ()--1/4 beatAtTempo: 60
				RatioLoudness ()--Ampl. ratio 0.4431
				RatioPitch ()--4/3 * basePitch

			OrdinalMagnitude ('table' 'Table' )--order-only, class or instance table
				Length ()--e.g., heartBeat > blink
				Sharpness ()--e.g., bright < glistening

	Protocols
	MusicMagnitude
			('accessing' value value:)
			('arithmetic' * + - / =)
			('comparing' < hash max: min:)
			('converting' mostGeneral)
			('printing' storeOn:)

	HertzPitch 
			('converting' asHertz asMIDI asSymbol mostGeneral)
			('printing' printOn:)
			('private' species)

	Extensibility of Magnitudes
		Adding new models

Events and EventLists
	MEvent and NoteEvent Classes
		MEvent abstraction--Dictionary with a duration--the rest is details.

	MEvent--has only duration, properties
		('initialize-release' release)
		('accessing' copy duration duration: inspect name name: species)
		('comparing' =)
		('properties' at: at:ifAbsent: at:put: doesNotUnderstand: properties)
		('testing' isEvent)
		('scheduling' scheduleAt:)

	NoteEvent--subclass of MEvent also has pitch, loudness, voice
		('initialize-release' release)
		('accessing' ampl ampl: dur dur: [. . .] voice voice:)
		('comparing' =)
		('scheduling' play schedule scheduleAt:)
		('printing' printOn: storeOn:)
		('processing' transposeBy:)

	Possibility (desirability?) of other Event classes
		RestEvent, MIDINote, etc.

	EventList--subclass of MEvent  with a time-sorted collection of event associations 
				i.e., (duration -> event)

	EventList protocols
		('initialize-release' empty initializeAnonymous initializeNamed: release reset)
		('accessing' deepCopy links linkTo: linkTo:via: . . . next shallowCopy)
		('event accessing' add: add:at: addAll: addModifier: 
			eventNear: eventNearTime: events events: items)
		('testing' hasItems isEventList species)
		('collecting' do: excerptFrom:to: expanded expandedFrom:to: group: 
			includes: notesDo: remove: select: timesDo:)
		('processing' addVoice: apply:to: apply:to:startingAt: chooseDuration: 
			chooseLoudness: . . .  scaleTempo: setDuration:  spreadLoudness:)
		('scheduling' play playAt: playOn: playOn:at: playPrim playPrimAt: scheduleAt:)
		('user interface' edit inspect)
		('printing' printOn: storeOn: storeOnFile:)
		('private' map: map:at:)

EventList Hierarchies
	Composition Hierarchy--use intermediate list levels for track, voice, riff, etc.
	Secondary Composition--Tree may be a forest (heterarchy)
	Link Hierarchies--arbitrary directed graphs --> HyperScores (!)
	Link Browsers--analysis editors, etc.
	EventList Dictionary-All named lists are persistent by default.
	A Hierarchy Example


Voices, Event I/O
	Events play by passing themselves to their voices, i.e.,

		NoteEvent methodsFor: scheduling
		play
			"play me now"
			^voice playEvent: self

	Voices as Device Drivers, as Property-to-Parameter mappers
	Concrete Voices: MIDI, Cmusic, Adagio, OpCode, CWare
	Voices and MIDIDevices--use sysEx facilities
		MIDIVoice on: aChannel: on: (MIDIDeviceFB01 new) on: aMIDIPort
	More on voices in HSTK V5.0 Doc


Schedulers and Real-Time
	EventList Performance and Scheduling

		EventList play method
			play
				"play NoteEvent data from my instance variables starting now"
				"(EventLists named: #temp.1) play."

			"		CHOOSE ONE OF:
						Use Smalltalk-80 scheduler and internal voices
				^self playOn: self voice at: (Time millisecondClockValue)
						Convert event list to MIDI Score and perform
				^self asScore play
						Dump Events to primitive scheduler
				^self playPrim
			"
				^self playPrim

	EventScheduler Protocols
		('initializing' initialize)
		('accessing' addAppointment: appointments: clients: dontWait running: wait)
		('running' callNextAppointment runAppointments setUpFirstAppointments)
		('updating' release update:)
		('interrupting' interrupt)

	EventScheduler performance methods
		runAppointments
			"Set up the first meetings and then run them all till no one wants a meeting anymore."

			running ifTrue: [^nil].
			self setUpFirstAppointments.		"set start time"
			self running: true.					"set flag"
											"as long as on"
			[(running == false) or: [appointments isEmpty]]
											"try next appointment"
					whileFalse: [self callNextAppointment].
			self running: false.				"cancel flag"


		callNextAppointment
			"Calls upon the next appointment to be made and then reschedules the next one"

			| entry entryClient nextTime time |
			entry _ appointments removeFirst.		"this is an association"
			time _ entry key.						"get the time"
			entryClient _ entry value.				"get the event or list"

			(doWait == true) ifTrue:				"if running in r-t"
				[(Delay untilMilliseconds: time) wait].	"wait"

		"	Transcript show: entryClient printString; cr.	"
			nextTime _ entry value scheduleAt: time.	"schedule it"
												"it returns the next start time or nil"
			nextTime == nil 						"re-add it if it returned anything"
					ifFalse: [appointments add: (nextTime => entryClient)]


	MIDI Primitive Class--GEG and LB's R-T Driver
		('accessing' getLong:at: putLong:into:at:)
		('playing' allOff play:at:dur:amp:)
		('primitive operations' close getClockTime getMode getReceiveCount
			getTickSize getTransmitCount killIO next: nextEvent: open put:count:
			set:data: setClockTime: setReadMode: setReceiveOff setReceiveOn
			setTickSize: status: test)
		('constants' mIDIMode rawMode)
		('mousing around' fromMouse)

		Primitive Example

			MIDI class methodsFor: 'primtive operations'
			 put: aByteArray count: anInteger

				<primitive: -104>
				^self primitiveFailed

		Primitives and the VM

		MIDI Processing EGens
			Echo, Transpose, Arpeggiator

EventGenerators and Modifiers
	EGens and Composition by Refinement

	EventList ('events' 'index' )
		EventGenerator ()--abstract
			Cloud ('density' )--stochastic generator
				DynamicCloud ()--describe pitch and duration selection surfaces
				SelectionCloud ()--define pitch and rhythm sets
					DynamicSelectionCloud ()--define transitions between sets
			Cluster ()--1-D set of pitches or rhythm
				Chord ('root' 'inversion' )--many chord creation messages
					Arpeggio ('delay' )--delayed performance of notes
				Roll ('number' 'delta' 'noteDuration' )--repeat a note
					Trill ()--repeat several notes
			Ostinato ('list' 'playing' 'process' )--generate notes as a process
				MarkhovTable ()--procedural variation of a set
				BellPeal ()--algorithmic composition method

	Other EGen abstractions possible...


	EMods
		Crescendo, Rubato, etc.
		See examples in System Outline




EventList Editors

	Three-part (traditional) MVC
		MVC Triad
		MVC Support
			Views
			Controllers
			UI Components


	Four-part MVC--Browsers, Inspectors and Editors
		Intermediate object holds "subject" + selection state;
			acts as a "protocol convertor" between controller and model.

	"Navigator "MVC
		Navigator Background and Examples

		DisplayItems, DisplayLists--structured graphics framework

		LayoutManagers--generating graphical structure representations

		ModelEditors--intermediaries, protocol convertors, accessors

		DisplayListViews/Controllers--generic application


	DisplayList Support Hierarchy

	DisplayObject ()--system class
		DisplayItem ('model' 'offset' 'extent' 'visual' )--node with visual object and its position and extent, 
						may know which model node it represents.
			DisplayLine ('width' 'mask' )--faster display of lines, no visual
			DisplayList ('items' )--collection of items and their boundingBox.
					List may have offset 0@0 or add its relative offset to its items'.


	DisplayItem ('model' 'offset' 'extent' 'visual' )
		('accessing' corner extent model model: offset offset: visual . . .)
		('display box access' boundingBox  bottomCenter . . .)
		('displaying' displayOn:at:clippingBox:rule:mask:)--most specific case
		('transforming' translateBy:)
		('printing' printOn:)


	DisplayList ('items' )
		('initialize-release' initialize)
		('accessing' add: add:at: collect: do: extent hasItems items nodeAt:)--add items and manage 
					model<-->item mapping
		('display box access' computeBoundingBox)
		('displaying' displayOn:at:clippingBox:rule:mask:)
		('geometry' reflect:)
		('transforming' translateBy:)
		('hit detection' itemsFromX:toX: itemsInRectangleOrigin:corner: 
			itemWithin:of: modelsFromX:toX:)--find item at a point
		('printing' printOn:)

	DisplayList class example

	DisplayList UI Classes

	View ('model' 'controller' 'superView' 'subViews' . . . 'insetDisplayBox' 
			'borderWidth' 'borderColor' 'insideColor' 'boundingBox' )--System View class, big
		DisplayListView ('cachedForm' 'list' 'xScale' 'yScale' )--general-purpose DLView
			TreeView ()--knows layout and controller
			SequenceView ('timeOffset' 'clefForm' )--knows x=time
				PitchTimeView ('pitchOffset' )-knows y=pitch
					CMNView ('clef' 'staves' )
					HauerSteffensView ('clef' )
				GroupingView ()--displays grouping
				PhraseView ()--displays prosidic phrase trees
				PositionTimeView ('positionOffset' )--y=left/right position
				SoundView ('ampScale' 'ampOffset' )--sampled sound, display samples or RMS envelopes


	DisplayListView Protocols
		('initialize release' initialize)
		('accessing' addItem: form list list: xRange . . . yScale:)
		('layout manager access' itemFor: layoutManager)
		('controller access' defaultControllerClass)
		('displaying' displayView redraw)
		('updating' update:with:from:)
		('scrolling' offsetX offsetX: offsetY scroll: scrollDown: . . . xPercent yPercent)
		('private' initForm)


	DisplayListController
		('initialize-release' initialize)
		('menu messages' blueButtonActivity inspect redraw zoom)


	LayoutManagers
		Take a data structure, an accessor, and some state, and
			 generate a displayList.


	LayoutManager Hierarchy
	LayoutManager ('view' 'orientation' 'itemAccessor' )
			('accessing' displayList displayListFor: orientation: view:)
			('generating' addItem:atNode:in: generateDisplayList)
		HierarchyLayoutManager ('length' 'xStep' 'yStep' 'treeAccessor' )
			IndentedListLayoutManager ()
				IndentedTreeLayoutManager ('list' )
			TreeLayoutManager ()
				TRTreeLayoutManager ()
		SequenceLayoutManager ('timeScale' 'timeOffset' )
			GroupingLayoutManager ('levelScale' )
			PitchTimeLayoutManager ('pitchScale' 'pitchOffset' )


	Structure Accessors
		e.g., TreeAccessor--childrenOf: aNode, isLeaf: aNode, nameOf: aNode

	Topaz UI Examples
		DisplayList example
		DisplayListView examples
		Music Structure Examples

	UI Support Classes
		EventInspector EventInspectorView
		EventListDictionaryInspector EventListDictionaryInspectorView 
		InstrumentSelector InstrumentSelectorController 
		NoteSelector SoundSelector
		PathEditor PathEditorController SplineEditor

	Old World HSTK V5.2 UI
		Category Music-ListEditors


Signals and Functions
		Path ('form' 'collectionOfPoints' )
			Function ('size' 'min' 'max' 'array' )
				Fourier ('myForm' 'myArray' )
				LinSeg ()
				SplineSeg ('myForm' )
				Signal
					Envelope
					SampledSound


Exercises

	Course VI
		Stripped HSTK V6.0 (Topaz)
		No Score/NoteElement/Adagio World, MIDI Devices, EventModifiers, Signals
		New Navigator-style DisplayList-based UI
		PrimScheduler with MIDI VM

	Topaz Sections in System Outline
		L:	Build HSTK 6.0
		M:	FileOut HSTK 6.0
		N:	Examples - Events and EventLists
		O:	Examples - EventGenerators and Modifiers
		P:	Examples - Reading and Writing EventList Files
		Q:	Examples - Scheduling
		R:	Examples - EventList Editors
		S:	Examples - GEG/LB's Primitive Scheduler
		T:	Examples - JHM's World
		U:	User Interface Buttons
		V:	Examples - Version 6.0 NewUI
		W:	June 1990 Course Notes Part 1
		X:	June 1990 Course Notes Part 2


Advanced Examples
	Build and annotate a list
		make some chords
		add links according to functional harmony relationships
		add links for text
		browse links with selection blocks

	Build a new PitchTimeView
		piano-roll layout manager
		new DisplayListView subclass

	Finish CMN Layout

	Finish TreeLayout and TRTree application code

	Fix DisplayListView scrolling


Topaz Classes
		('Music-Magnitudes' Amplitude ConditionalDuration Duration HertzPitch
			Length MIDIPitch MIDIVelocity MSecondDuration MusicMagnitude 
			NominalMagnitude NumericalMagnitude OrdinalMagnitude PField Pitch 
			RatioDuration RatioLoudness RatioMagnitude RatioPitch Sharpness 
			SymbolicLoudness SymbolicPitch)

		('Music-Events' EventAssociation EventList EventScheduler MEvent NoteEvent)

		('Music-Voices' CmusicVoice OpcodeVoice2 Voice)

		('Music-Functions' Fourier Function LinSeg SplineSeg)

		('Music-EventGenerators' Arpeggio Chord Cloud Cluster DynamicCloud 
			DynamicSelectionCloud EventGenerator Ostinato Roll SelectionCloud Trill)

		('Music-DisplayLists' DisplayItem DisplayLine DisplayList 
			DisplayListController DisplayListView)

		('Music-Layout' GroupingLayoutManager HierarchyLayoutManager
			IndentedListLayoutManager IndentedTreeLayoutManager
			LayoutManager PitchTimeLayoutManager SequenceLayoutManager
			TreeAccessor TreeLayoutManager TRTreeLayoutManager)

		('Music-Editors' CMNView GroupingView HauerSteffensView PhraseView
			PitchTimeController PitchTimeView PositionTimeView SequenceController
			SequenceView SoundView)

		('Music-Trees' BTreeNode TreeController TreeView TRTree
			TRTreeEditor TrTreeEditorController TRTreeNode)

		('Music-UI-Support' EventInspector EventInspectorView
			EventListDictionaryInspector EventListDictionaryInspectorView
			InstrumentSelector InstrumentSelectorController NoteSelector
			PathEditor PathEditorController SoundSelector SplineEditor)

		('Music-ListEditors' EventListEditor EventListEditorController
			EventListView HSEventListView PianoView SoundMixView StringQView)

		('Music-MIDI' MIDI)

		('Interface-Gauges' BarGauge BarGaugeController BeadGauge
			GaugeButtonView GaugeView RectangularGauge SlideGauge ValueGauge)

		('Interface-Outlines' Outline OutlineBrowser)

