[Vm-dev] VM Maker: VMMaker.oscog-eem.2785.mcz
karl ramberg
karlramberg at gmail.com
Sat Aug 1 18:41:32 UTC 2020
Cool. I've seen people asking about higher bit depth in Sound plugin. Maybe
that will be easier to add now ?
Best,
Karl
On Sat, Aug 1, 2020 at 4:45 AM <commits at source.squeak.org> wrote:
>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2785.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2785
> Author: eem
> Time: 31 July 2020, 7:45:15.985473 pm
> UUID: 9fa77ef1-7255-47f3-9dd1-c500f9529cbb
> Ancestors: VMMaker.oscog-eem.2784
>
> Plugins: Clean up the SoundPlugin, eloiminating almost all cCode:'s,
> making it potentially simulateable once the internal API is implemented.
> Use the methodRetur...: API to simplify a number of primitives. Change
> primitiveSoundEnableAEC to take either 0, 1 or a boolean.
>
> Slang: eliminate the arguments to addressOf:put: blocks via
> nodeIsDeadCode:withParent:
>
> Simulation: implement unsigned coercion in cCoerce:to: to support this
> form in primitiveSoundEnableAEC
> (interpreterProxy isIntegerObject: (arg := interpreterProxy
> stackValue: 0))
> ifTrue:
> [arg := interpreterProxy integerValueOf: arg.
> (interpreterProxy cCoerce: arg to: #unsigned) > 1
> ifTrue:
> [^interpreterProxy primitiveFailFor:
> PrimErrBadArgument].
> trueOrFalse := arg = 1]
> ifFalse:
> [(interpreterProxy isBooleanObject: arg) ifFalse:
> [^interpreterProxy primitiveFailFor:
> PrimErrBadArgument].
> trueOrFalse := interpreterProxy booleanValueOf:
> arg].
>
> =============== Diff against VMMaker.oscog-eem.2784 ===============
>
> Item was changed:
> ----- Method: CCodeGenerator>>nodeIsDeadCode:withParent: (in category
> 'utilities') -----
> nodeIsDeadCode: aNode withParent: parentNode
> "Answer if aNode would not be generated due to dead code
> elimination."
> + (aNode isLiteralBlock and: [parentNode isSend and: [parentNode
> selector == #addressOf:put:]]) ifTrue:
> + [^true].
> ^(self nilOrBooleanConditionFor: parentNode)
> ifNil: [false]
> ifNotNil:
> [:cond| | filter |
> filter := parentNode selector caseOf:
> { "First element
> is accessor for filtered (eliminated) node if expression is true.
> Second
> element is accessor for filtered (eliminated) node if expression is false."
>
> [#ifFalse:] -> [#(first nil)].
>
> [#ifFalse:ifTrue:] -> [#(first last)].
>
> [#ifTrue:] -> [#(nil first)].
>
> [#ifTrue:ifFalse:] -> [#(last first)].
> [#and:]
> -> [#(nil first)].
> [#or:]
> -> [#(last nil)].
>
> [#cppIf:ifTrue:] -> [#(nil #second)].
>
> [#cppIf:ifTrue:ifFalse:] -> [#(third #second)] }.
> (cond ifTrue: [filter first] ifFalse: [filter
> last])
> ifNil: [false]
> ifNotNil: [:accessor| aNode == (parentNode
> args perform: accessor)]]!
>
> Item was changed:
> ----- Method: Integer>>coerceTo:sim: (in category '*VMMaker-interpreter
> simulator') -----
> coerceTo: cTypeString sim: interpreter
>
> | unitSize |
> + cTypeString last == $* ifTrue: "C pointer"
> - cTypeString last = $* ifTrue: "C pointer"
> [unitSize := cTypeString caseOf: {
> [#'char *'] -> [1].
> [#'short *'] -> [2].
> [#'int *'] -> [4].
> [#'long long *'] -> [8].
> [#'float *'] -> [^CFloatArray basicNew interpreter:
> interpreter address: self unitSize: 4; yourself].
> [#'double *'] -> [^CFloatArray basicNew interpreter:
> interpreter address: self unitSize: 8; yourself].
> [#'unsigned *'] -> [4].
> [#'unsigned int *'] -> [4].
> [#'unsigned char *'] -> [1].
> [#'signed char *'] -> [1].
> [#'unsigned short *'] -> [2].
> [#'unsigned long long *'] -> [8].
> [#'oop *'] -> [interpreter objectMemory bytesPerOop].
> }
> otherwise: [interpreter objectMemory wordSize].
> ^CArray basicNew
> interpreter: interpreter address: self unitSize:
> unitSize;
> yourself].
> + cTypeString first == $u ifTrue:
> + [unitSize := cTypeString caseOf: {
> + [#usqInt] -> [interpreter objectMemory wordSize].
> + [#usqLong] -> [8].
> + [#unsigned] -> [4].
> + [#'unsigned int'] -> [4].
> + [#'unsigned char'] -> [1].
> + [#'unsigned long'] -> [6].
> + [#'unsigned short'] -> [2].
> + [#'unsigned long long'] -> [8].
> + }
> + otherwise: [self error: 'unknown unsigned type name'].
> + ^self bitAnd: 1 << (8 * unitSize) - 1].
> + ^self "C number (int, char, etc)"!
> - ^self "C number (int, char, float, etc)"!
>
> Item was added:
> + ----- Method: InterpreterProxy>>cCoerce:to: (in category 'simulation
> only') -----
> + cCoerce: value to: cTypeString
> + "Type coercion. For translation a cast will be emitted. When
> running in Smalltalk
> + answer a suitable wrapper for correct indexing."
> + ^value
> + ifNil: [value]
> + ifNotNil: [value coerceTo: cTypeString sim: self]!
>
> Item was changed:
> ----- Method: RePlugin>>rcvrMatchSpacePtr (in category 'rcvr linkage')
> -----
> rcvrMatchSpacePtr
>
> <inline: true>
> <returnTypeC: 'int *'>
> ^self
> cCoerce: (interpreterProxy fetchArray: 7 ofObject: rcvr)
> + to: #'int *'!
> - to: 'int *'.!
>
> Item was changed:
> ----- Method: RePlugin>>rcvrPatternStrPtr (in category 'rcvr linkage')
> -----
> rcvrPatternStrPtr
>
> <inline: true>
> <returnTypeC: 'char *'>
> ^self
> cCoerce: (interpreterProxy fetchArray: 0 ofObject: rcvr)
> + to: #'char *'.!
> - to: 'char *'.!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetDefaultSoundPlayer (in category
> 'primitives') -----
> primitiveGetDefaultSoundPlayer
> "Answer a String with the operating system name of the default
> output device, or nil"
> "no arguments"
> - | cDeviceName sz newString newStringPtr |
> <export: true>
> + | cDeviceName |
> + <var: #cDeviceName type: #'char*'>
> - <var: #cDeviceName type: 'char*'>
> - <var: #newStringPtr type: 'char*'>
>
> - "Parse arguments"
> - interpreterProxy methodArgumentCount = 0
> - ifFalse:[^interpreterProxy primitiveFail].
> -
> "Get the answer."
> + cDeviceName := self getDefaultSoundPlayer.
> + cDeviceName = 0 ifTrue:
> + [^interpreterProxy methodReturnValue: interpreterProxy
> nilObject].
> - cDeviceName := self cCode: 'getDefaultSoundPlayer()'.
> - cDeviceName == 0 ifTrue: [
> - ^interpreterProxy pop: 1 thenPush: interpreterProxy
> nilObject
> - ].
>
> + ^interpreterProxy methodReturnString: cDeviceName!
> - "Copy the answer to a Squeak String."
> - sz := self cCode: 'strlen(cDeviceName)'.
> - newString := interpreterProxy
> -
> instantiateClass: interpreterProxy classString
> -
> indexableSize: sz.
> - newStringPtr := interpreterProxy firstIndexableField: newString.
> - self cCode: 'strncpy(newStringPtr, cDeviceName, sz)'.
> -
> - self touch: newStringPtr.
> - self touch: cDeviceName.
> - "Pop the receiver, and answer the new string."
> - ^interpreterProxy pop: 1 thenPush: newString!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetDefaultSoundRecorder (in category
> 'primitives') -----
> primitiveGetDefaultSoundRecorder
> "Answer a String with the operating system name of the default
> input device, or nil"
> "no arguments"
> - | cDeviceName sz newString newStringPtr |
> <export: true>
> + | cDeviceName |
> + <var: #cDeviceName type: #'char*'>
> - <var: #cDeviceName type: 'char*'>
> - <var: #newStringPtr type: 'char*'>
>
> - "Parse arguments"
> - interpreterProxy methodArgumentCount = 0
> - ifFalse:[^interpreterProxy primitiveFail].
> -
> "Get the answer."
> + cDeviceName := self getDefaultSoundRecorder.
> + cDeviceName = 0 ifTrue:
> + [^interpreterProxy methodReturnValue: interpreterProxy
> nilObject].
> - cDeviceName := self cCode: 'getDefaultSoundRecorder()'.
> - cDeviceName == 0 ifTrue: [
> - ^interpreterProxy pop: 1 thenPush: interpreterProxy
> nilObject
> - ].
>
> + ^interpreterProxy methodReturnString: cDeviceName!
> - "Copy the answer to a Squeak String."
> - sz := self cCode: 'strlen(cDeviceName)'.
> - newString := interpreterProxy
> -
> instantiateClass: interpreterProxy classString
> -
> indexableSize: sz.
> - newStringPtr := interpreterProxy firstIndexableField: newString.
> - self cCode: 'strncpy(newStringPtr, cDeviceName, sz)'.
> -
> - self touch: newStringPtr.
> - self touch: cDeviceName.
> - "Pop the receiver, and answer the new string."
> - ^interpreterProxy pop: 1 thenPush: newString!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetNumberOfSoundPlayerDevices (in
> category 'primitives') -----
> primitiveGetNumberOfSoundPlayerDevices
> - "arguments: name(type, stack offset)
> - dialString(String, 0)"
> - "answers an Integer"
> - | result |
> <export: true>
>
> + ^interpreterProxy methodReturnInteger: self
> getNumberOfSoundPlayerDevices!
> - "Parse arguments"
> - interpreterProxy methodArgumentCount = 0
> - ifFalse:[^interpreterProxy primitiveFail].
> -
> - "get result"
> - result := self cCode: 'getNumberOfSoundPlayerDevices()'.
> -
> - "answer it"
> - result := interpreterProxy signed32BitIntegerFor: result.
> - ^interpreterProxy pop: 1 thenPush: result. "pop receiver, return
> result"!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetNumberOfSoundRecorderDevices (in
> category 'primitives') -----
> primitiveGetNumberOfSoundRecorderDevices
> - "arguments: name(type, stack offset)
> - dialString(String, 0)"
> - "answers an Integer"
> - | result |
> <export: true>
>
> + ^interpreterProxy methodReturnInteger: self
> getNumberOfSoundRecorderDevices!
> - "Parse arguments"
> - interpreterProxy methodArgumentCount = 0
> - ifFalse:[^interpreterProxy primitiveFail].
> -
> - "get result"
> - result := self cCode: 'getNumberOfSoundRecorderDevices()'.
> -
> - "answer it"
> - result := interpreterProxy signed32BitIntegerFor: result.
> - ^interpreterProxy pop: 1 thenPush: result. "pop receiver, return
> result"!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetSoundPlayerDeviceName (in
> category 'primitives') -----
> primitiveGetSoundPlayerDeviceName
> "arguments: name(type, stack offset)
> deviceNumber(Integer, 0)"
> "answers a string or nil"
> - | deviceNumber sz cDeviceName newString newStringPtr |
> <export: true>
> + | deviceNumber cDeviceName |
> + <var: #cDeviceName type: #'char *'>
> - <var: #cDeviceName type: 'char*'>
> - <var: #newStringPtr type: 'char*'>
>
> "Parse arguments"
> + interpreterProxy methodArgumentCount = 1 ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
> - interpreterProxy methodArgumentCount = 1
> - ifFalse:[^interpreterProxy primitiveFail].
>
> deviceNumber := interpreterProxy positive32BitValueOf:
> (interpreterProxy stackValue: 0).
> + interpreterProxy failed ifTrue:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> - interpreterProxy failed ifTrue: [^nil].
>
> "Get the answer."
> + cDeviceName := self getSoundPlayerDeviceName: deviceNumber - 1.
> + cDeviceName = 0 ifTrue:
> + [^interpreterProxy methodReturnValue: interpreterProxy
> nilObject].
> - cDeviceName := self cCode: 'getSoundPlayerDeviceName(deviceNumber
> - 1)'.
> - cDeviceName == 0 ifTrue: [
> - ^interpreterProxy pop: 2 thenPush: interpreterProxy
> nilObject
> - ].
>
> + ^interpreterProxy methodReturnString: cDeviceName!
> - "Copy the answer to a Squeak String."
> - sz := self cCode: 'strlen(cDeviceName)'.
> - newString := interpreterProxy
> -
> instantiateClass: interpreterProxy classString
> -
> indexableSize: sz.
> - newStringPtr := interpreterProxy firstIndexableField: newString.
> - self cCode: 'strncpy(newStringPtr, cDeviceName, sz)'.
> -
> - self touch: deviceNumber.
> - self touch: newStringPtr.
> - self touch: cDeviceName.
> - "Pop the receiver and arg, and answer the new string."
> - ^interpreterProxy pop: 2 thenPush: newString!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveGetSoundRecorderDeviceName (in
> category 'primitives') -----
> primitiveGetSoundRecorderDeviceName
> "arguments: name(type, stack offset)
> deviceNumber(Integer, 0)"
> "answers a string or nil"
> - | deviceNumber sz cDeviceName newString newStringPtr |
> <export: true>
> + | deviceNumber cDeviceName |
> + <var: #cDeviceName type: #'char *'>
> - <var: #cDeviceName type: 'char*'>
> - <var: #newStringPtr type: 'char*'>
>
> "Parse arguments"
> + interpreterProxy methodArgumentCount = 1 ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
> - interpreterProxy methodArgumentCount = 1
> - ifFalse:[^interpreterProxy primitiveFail].
>
> -
> deviceNumber := interpreterProxy positive32BitValueOf:
> (interpreterProxy stackValue: 0).
> + interpreterProxy failed ifTrue:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> - interpreterProxy failed ifTrue: [^nil].
>
> "Get the answer."
> + cDeviceName := self getSoundRecorderDeviceName: deviceNumber - 1.
> + cDeviceName = 0 ifTrue:
> + [^interpreterProxy methodReturnValue: interpreterProxy
> nilObject].
> - cDeviceName := self cCode:
> 'getSoundRecorderDeviceName(deviceNumber - 1)'.
> - cDeviceName == 0 ifTrue: [
> - ^interpreterProxy pop: 2 thenPush: interpreterProxy
> nilObject
> - ].
>
> + ^interpreterProxy methodReturnString: cDeviceName!
> - "Copy the answer to a Squeak String."
> - sz := self cCode: 'strlen(cDeviceName)'.
> - newString := interpreterProxy
> -
> instantiateClass: interpreterProxy classString
> -
> indexableSize: sz.
> - newStringPtr := interpreterProxy firstIndexableField: newString.
> - self cCode: 'strncpy(newStringPtr, cDeviceName, sz)'.
> -
> - self touch: deviceNumber.
> - self touch: newStringPtr.
> - self touch: cDeviceName.
> - "Pop the receiver and arg, and answer the new string."
> - ^interpreterProxy pop: 2 thenPush: newString!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSetDefaultSoundPlayer (in category
> 'primitives') -----
> primitiveSetDefaultSoundPlayer
> "Tell the operating system to use the specified device name as the
> output device for sound."
> "arg at top of stack is the String"
> - | deviceName obj srcPtr sz |
> <export: true>
> + | deviceName obj srcPtr sz |
> <var: 'deviceName' declareC: 'char deviceName[257]'>
> <var: 'srcPtr' type: #'char *'>
> + self cCode: [] inSmalltalk: [deviceName := ByteString new: 257].
> -
> "Parse arguments"
> interpreterProxy methodArgumentCount = 1 ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
> + ((interpreterProxy isBytes: (obj := interpreterProxy stackValue:
> 0))
> + and: [(sz := interpreterProxy byteSizeOf: obj) <= 256]) ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> +
> + srcPtr := self cCoerce: (interpreterProxy firstIndexableField:
> obj) to: #'char *'.
> + self strncpy: deviceName _: srcPtr _: sz.
> + deviceName at: sz put: 0.
> + self setDefaultSoundPlayer: deviceName.
> +
> + interpreterProxy failed ifFalse:
> + [interpreterProxy methodReturnReceiver]!
> - [^interpreterProxy primitiveFail].
> - obj := interpreterProxy stackValue: 0.
> - (interpreterProxy isBytes: obj) ifFalse:
> - [^interpreterProxy primitiveFail].
> - (sz := interpreterProxy byteSizeOf: obj) <= 256 ifFalse:
> - [^interpreterProxy primitiveFail].
> - srcPtr := interpreterProxy firstIndexableField: obj.
> - self touch: srcPtr.
> - self touch: deviceName.
> - self touch: sz.
> - self cCode: 'strncpy(deviceName, srcPtr, sz)'.
> - self cCode: 'deviceName[sz] = 0'.
> -
> - "do the work"
> - self cCode: 'setDefaultSoundPlayer(deviceName)'.
> - interpreterProxy failed ifFalse: "pop arg, leave receiver"
> - [interpreterProxy pop: 1]!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSetDefaultSoundRecorder (in category
> 'primitives') -----
> primitiveSetDefaultSoundRecorder
> "Tell the operating system to use the specified device name as the
> input device for sound."
> "arg at top of stack is the String"
> - | deviceName obj srcPtr sz |
> <export: true>
> + | deviceName obj srcPtr sz |
> <var: 'deviceName' declareC: 'char deviceName[257]'>
> <var: 'srcPtr' type: #'char *'>
> + self cCode: [] inSmalltalk: [deviceName := ByteString new: 257].
> -
> "Parse arguments"
> interpreterProxy methodArgumentCount = 1 ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
> + ((interpreterProxy isBytes: (obj := interpreterProxy stackValue:
> 0))
> + and: [(sz := interpreterProxy byteSizeOf: obj) <= 256]) ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> +
> + srcPtr := self cCoerce: (interpreterProxy firstIndexableField:
> obj) to: #'char *'.
> + self strncpy: deviceName _: srcPtr _: sz.
> + deviceName at: sz put: 0.
> + self setDefaultSoundRecorder: deviceName.
> +
> + interpreterProxy failed ifFalse:
> + [interpreterProxy methodReturnReceiver]!
> - [^interpreterProxy primitiveFail].
> - obj := interpreterProxy stackValue: 0.
> - (interpreterProxy isBytes: obj) ifFalse:
> - [^interpreterProxy primitiveFail].
> - (sz := interpreterProxy byteSizeOf: obj) <= 256 ifFalse:
> - [^interpreterProxy primitiveFail].
> - srcPtr := interpreterProxy firstIndexableField: obj.
> - self touch: srcPtr.
> - self touch: deviceName.
> - self touch: sz.
> - self cCode: 'strncpy(deviceName, srcPtr, sz)'.
> - self cCode: 'deviceName[sz] = 0'.
> -
> - "do the work"
> - self cCode: 'setDefaultSoundRecorder(deviceName)'.
> - interpreterProxy failed ifFalse: "pop arg, leave receiver"
> - [interpreterProxy pop: 1]!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundAvailableSpace (in category
> 'primitives') -----
> primitiveSoundAvailableSpace
> + "Returns the number of bytes of available sound output buffer
> space.
> + This should be (frames*4) if the device is in stereo mode, or
> (frames*2) otherwise"
> - "Returns the number of bytes of available sound output buffer
> space. This should be (frames*4) if the device is in stereo mode, or
> (frames*2) otherwise"
>
> + <export: true>
> | frames |
> + frames := self snd_AvailableSpace. "-1 if sound output not
> started"
> + frames >= 0
> + ifTrue: [interpreterProxy methodReturnInteger: frames]
> + ifFalse: [interpreterProxy primitiveFail]!
> - self primitive: 'primitiveSoundAvailableSpace'.
> - frames := self cCode: 'snd_AvailableSpace()'. "-1 if sound output
> not started"
> - interpreterProxy success: frames >= 0.
> - ^frames asPositiveIntegerObj!
>
> Item was added:
> + ----- Method: SoundPlugin>>primitiveSoundEnableAEC (in category
> 'primitives') -----
> + primitiveSoundEnableAEC
> + "Enable or disable acoustic echo-cancellation (AEC).
> + Arg is a boolean or 1 for true and 0 for false."
> + <export: true>
> + | arg trueOrFalse errorCode |
> + interpreterProxy methodArgumentCount = 1 ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
> + "Parse arguments"
> + (interpreterProxy isIntegerObject: (arg := interpreterProxy
> stackValue: 0))
> + ifTrue:
> + [arg := interpreterProxy integerValueOf: arg.
> + (interpreterProxy cCoerce: arg to: #unsigned) > 1
> ifTrue:
> + [^interpreterProxy primitiveFailFor:
> PrimErrBadArgument].
> + trueOrFalse := arg = 1]
> + ifFalse:
> + [(interpreterProxy isBooleanObject: arg) ifFalse:
> + [^interpreterProxy primitiveFailFor:
> PrimErrBadArgument].
> + trueOrFalse := interpreterProxy booleanValueOf:
> arg].
> + "Set AEC"
> + (errorCode := self snd_EnableAEC: trueOrFalse) ~= 0 ifTrue:
> + [interpreterProxy primitiveFailFor: (errorCode < 0 ifTrue:
> [PrimErrGenericFailure] ifFalse: [errorCode])]!
>
> Item was removed:
> - ----- Method: SoundPlugin>>primitiveSoundEnableAEC: (in category
> 'primitives') -----
> - primitiveSoundEnableAEC: trueOrFalse
> - "Enable or disable acoustic echo-cancellation (AEC). trueOrFalse
> should be 0 for false, and 1 for true."
> - | result |
> - self primitive: 'primitiveSoundEnableAEC' parameters:
> #(SmallInteger ).
> - interpreterProxy failed ifFalse: [
> - result := self cCode: 'snd_EnableAEC(trueOrFalse)'.
> - result == 0 ifFalse: [interpreterProxy primitiveFailFor:
> result].
> - ].!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundGetRecordLevel (in category
> 'primitives') -----
> primitiveSoundGetRecordLevel
> + "Get the default input device's volume level in the range 0-1000."
> + <export: true>
> - "Get the sound input recording level in the range 0-1000."
> | level |
> <var: 'level' type: #int>
> + level := self snd_GetRecordLevel.
> + ^level >= 0
> + ifTrue: [interpreterProxy methodReturnInteger: level]
> + ifFalse: [interpreterProxy primitiveFail]!
> - self primitive: 'primitiveSoundGetRecordLevel'.
> - level := self cCode: 'snd_GetRecordLevel()'.
> - ^level asPositiveIntegerObj
> - !
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundGetRecordingSampleRate (in
> category 'primitives') -----
> primitiveSoundGetRecordingSampleRate
> "Return a float representing the actual sampling rate during
> recording. Fail if not currently recording."
>
> + <export: true>
> | rate |
> + <var: #rate type: #double>
> + rate := self snd_GetRecordingSampleRate. "fails if not recording"
> + interpreterProxy failed ifFalse:
> + [^interpreterProxy methodReturnFloat: rate]!
> - <var: #rate type: 'double '>
> - self primitive: 'primitiveSoundGetRecordingSampleRate'.
> - rate := self cCode: 'snd_GetRecordingSampleRate()'. "fail if not
> recording"
> - ^rate asFloatObj!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundGetVolume (in category
> 'primitives') -----
> primitiveSoundGetVolume
> + "Get the default output device's volume level as a left/right pair
> of floats in the range 0-1."
> + <export: true>
> + | left right leftOop rightOop results |
> - "Get the sound input recording level."
> - | left right results |
> <var: #left type: #double>
> <var: #right type: #double>
> + left := 0.0.
> + right := 0.0.
> + self snd_Volume: (self addressOf: left put: [:v| left := v]) _:
> (self addressOf: right put: [:v| right := v]).
> + interpreterProxy failed ifTrue:
> + [^self].
> + results := interpreterProxy instantiateClass: interpreterProxy
> classArray indexableSize: 2.
> + results ifNil:
> + [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
> + self remapOop: results in:
> + [leftOop := interpreterProxy floatObjectOf: left.
> + self remapOop: leftOop in:
> + [rightOop := interpreterProxy floatObjectOf:
> right]].
> + interpreterProxy
> + storePointer: 0 ofObject: results withValue: leftOop;
> + storePointer: 1 ofObject: results withValue: rightOop;
> + methodReturnValue: results!
> - self primitive: 'primitiveSoundGetVolume'
> - parameters: #( ).
> - left := 0.
> - right := 0.
> - self cCode: 'snd_Volume((double *) &left,(double *) &right)'.
> - interpreterProxy pushRemappableOop: (right asOop: Float).
> - interpreterProxy pushRemappableOop: (left asOop: Float).
> - results := interpreterProxy instantiateClass: (interpreterProxy
> classArray) indexableSize: 2.
> - interpreterProxy storePointer: 0 ofObject: results withValue:
> interpreterProxy popRemappableOop.
> - interpreterProxy storePointer: 1 ofObject: results withValue:
> interpreterProxy popRemappableOop.
> - ^results!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundInsertSamples:from:leadTime:
> (in category 'primitives') -----
> primitiveSoundInsertSamples: frameCount from: buf leadTime: leadTime
> "Insert a buffer's worth of sound samples into the currently
> playing
> buffer. Used to make a sound start playing as quickly as possible.
> The
> new sound is mixed with the previously buffered sampled."
> "Details: Unlike primitiveSoundPlaySamples, this primitive always
> starts
> with the first sample the given sample buffer. Its third argument
> specifies the number of samples past the estimated sound output
> buffer
> position the inserted sound should start. If successful, it
> returns the
> number of samples inserted."
> | framesPlayed |
> self primitive: 'primitiveSoundInsertSamples'
> + parameters: #(SmallInteger WordArray SmallInteger).
> + frameCount <= (interpreterProxy slotSizeOf: buf cPtrAsOop) ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> - parameters: #(SmallInteger WordArray SmallInteger ).
> - interpreterProxy success: frameCount <= (interpreterProxy
> slotSizeOf: buf cPtrAsOop).
>
> + framesPlayed := self snd_InsertSamplesFromLeadTime: frameCount _:
> buf _: leadTime.
> + framesPlayed >= 0
> + ifTrue: [interpreterProxy methodReturnInteger:
> framesPlayed]
> + ifFalse: [interpreterProxy primitiveFail]!
> - interpreterProxy failed
> - ifFalse: [framesPlayed := self cCode:
> 'snd_InsertSamplesFromLeadTime(frameCount, (void *)buf, leadTime)'.
> - interpreterProxy success: framesPlayed >= 0].
> - ^ framesPlayed asPositiveIntegerObj!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundPlaySamples:from:startingAt:
> (in category 'primitives') -----
> primitiveSoundPlaySamples: frameCount from: buf startingAt: startIndex
> "Output a buffer's worth of sound samples."
> | framesPlayed |
> self primitive: 'primitiveSoundPlaySamples'
> + parameters: #(SmallInteger WordArray SmallInteger).
> + (startIndex >= 1 and: [startIndex + frameCount - 1 <=
> (interpreterProxy slotSizeOf: buf cPtrAsOop)]) ifTrue:
> + [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
> - parameters: #(SmallInteger WordArray SmallInteger ).
> - interpreterProxy success: (startIndex >= 1 and: [startIndex +
> frameCount - 1 <= (interpreterProxy slotSizeOf: buf cPtrAsOop)]).
>
> + framesPlayed := self snd_PlaySamplesFromAtLength: frameCount _:
> buf _: startIndex - 1.
> + framesPlayed >= 0
> + ifTrue: [interpreterProxy methodReturnInteger:
> framesPlayed]
> + ifFalse: [interpreterProxy primitiveFail]!
> - interpreterProxy failed
> - ifFalse: [framesPlayed := self cCode:
> 'snd_PlaySamplesFromAtLength(frameCount, (void *)buf, startIndex - 1)'.
> - interpreterProxy success: framesPlayed >= 0].
> - ^ framesPlayed asPositiveIntegerObj!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundPlaySilence (in category
> 'primitives') -----
> primitiveSoundPlaySilence
> "Output a buffer's worth of silence. Returns the number of sample
> frames played."
>
> + <export: true>
> | framesPlayed |
> + framesPlayed := self snd_PlaySilence. "-1 if sound output not
> started"
> + framesPlayed >= 0
> + ifTrue: [interpreterProxy methodReturnInteger:
> framesPlayed]
> + ifFalse: [interpreterProxy primitiveFail]!
> - self primitive: 'primitiveSoundPlaySilence'.
> - framesPlayed := self cCode: 'snd_PlaySilence()'. "-1 if sound
> output not started"
> - interpreterProxy success: framesPlayed >= 0.
> - ^framesPlayed asPositiveIntegerObj!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundRecordSamplesInto:startingAt:
> (in category 'primitives') -----
> primitiveSoundRecordSamplesInto: buf startingAt: startWordIndex
> "Record a buffer's worth of 16-bit sound samples."
> + | bufSizeInBytes samplesRecorded bufPtr byteOffset |
> - | bufSizeInBytes samplesRecorded bufPtr byteOffset bufLen |
> <var: #bufPtr type: #'char*'>
> self primitive: 'primitiveSoundRecordSamples'
> + parameters: #(WordArray SmallInteger).
> - parameters: #(WordArray SmallInteger ).
>
> + bufSizeInBytes := (interpreterProxy slotSizeOf: buf cPtrAsOop) * 4.
> + byteOffset := (startWordIndex - 1) * 2.
> - interpreterProxy failed ifFalse:
> - [bufSizeInBytes := (interpreterProxy slotSizeOf: buf
> cPtrAsOop) * 4.
> - interpreterProxy success: (startWordIndex >= 1 and:
> [startWordIndex - 1 * 2 < bufSizeInBytes])].
>
> + (startWordIndex >= 1 and: [byteOffset < bufSizeInBytes]) ifFalse:
> + [^interpreterProxy primitiveFailFor: PrimErrBadIndex].
> - interpreterProxy failed ifFalse:[
> - byteOffset := (startWordIndex - 1) * 2.
> - bufPtr := (self cCoerce: buf to: 'char*') + byteOffset.
> - bufLen := bufSizeInBytes - byteOffset.
> - samplesRecorded := self cCode:
> 'snd_RecordSamplesIntoAtLength(bufPtr, 0, bufLen)' inSmalltalk:[bufPtr.
> bufLen. 0].
> - ].
>
> + bufPtr := (self cCoerce: buf to: #'char *') + byteOffset.
> + samplesRecorded := self snd_RecordSamplesIntoAtLength: bufPtr _: 0
> _: bufSizeInBytes - byteOffset.
> + interpreterProxy failed ifFalse:
> + [^samplesRecorded asPositiveIntegerObj]!
> - ^ samplesRecorded asPositiveIntegerObj!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundSetLeftVolume:rightVolume: (in
> category 'primitives') -----
> primitiveSoundSetLeftVolume: aLeftVolume rightVolume: aRightVolume
> "Set the sound input recording level."
>
> self primitive: 'primitiveSoundSetLeftVolume'
> parameters: #(Float Float).
> + self snd_SetVolume: aLeftVolume _: aRightVolume!
> - interpreterProxy failed ifFalse: [self cCode:
> 'snd_SetVolume(aLeftVolume,aRightVolume)'].
> - !
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundSetRecordLevel: (in category
> 'primitives') -----
> primitiveSoundSetRecordLevel: level
> "Set the sound input recording level."
> self primitive: 'primitiveSoundSetRecordLevel'
> + parameters: #(SmallInteger).
> + self snd_SetRecordLevel: level!
> - parameters: #(SmallInteger ).
> - interpreterProxy failed ifFalse: [self cCode:
> 'snd_SetRecordLevel(level)']!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundStartBufferSize:rate:stereo:
> (in category 'primitives') -----
> primitiveSoundStartBufferSize: bufFrames rate: samplesPerSec stereo:
> stereoFlag
> "Start the double-buffered sound output with the given buffer
> size, sample rate, and stereo flag."
>
> self primitive: 'primitiveSoundStart'
> parameters: #(SmallInteger SmallInteger Boolean).
> + interpreterProxy success: (self snd_Start: bufFrames _:
> samplesPerSec _: stereoFlag _: 0)!
> - interpreterProxy success: (self cCode: 'snd_Start(bufFrames,
> samplesPerSec, stereoFlag, 0)')!
>
> Item was changed:
> ----- Method:
> SoundPlugin>>primitiveSoundStartBufferSize:rate:stereo:semaIndex: (in
> category 'primitives') -----
> primitiveSoundStartBufferSize: bufFrames rate: samplesPerSec stereo:
> stereoFlag semaIndex: semaIndex
> "Start the double-buffered sound output with the given buffer
> size, sample rate, stereo flag, and semaphore index."
>
> self primitive: 'primitiveSoundStartWithSemaphore'
> parameters: #(SmallInteger SmallInteger Boolean
> SmallInteger).
> + interpreterProxy success: (self snd_Start: bufFrames _:
> samplesPerSec _: stereoFlag _: semaIndex)!
> - interpreterProxy success: (self cCode: 'snd_Start(bufFrames,
> samplesPerSec, stereoFlag, semaIndex)')!
>
> Item was changed:
> ----- Method:
> SoundPlugin>>primitiveSoundStartRecordingDesiredSampleRate:stereo:semaIndex:
> (in category 'primitives') -----
> primitiveSoundStartRecordingDesiredSampleRate: desiredSamplesPerSec
> stereo: stereoFlag semaIndex: semaIndex
> "Start recording sound with the given parameters."
>
> self primitive: 'primitiveSoundStartRecording'
> parameters: #(SmallInteger Boolean SmallInteger).
> + self snd_StartRecording: desiredSamplesPerSec _: stereoFlag _:
> semaIndex!
> - self cCode: 'snd_StartRecording(desiredSamplesPerSec, stereoFlag,
> semaIndex)'!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundStop (in category 'primitives')
> -----
> primitiveSoundStop
> "Stop double-buffered sound output."
> + <export: true>
> + self snd_Stop!
> -
> - self primitive: 'primitiveSoundStop'.
> -
> - self cCode: 'snd_Stop()'. "leave rcvr on stack"!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundStopRecording (in category
> 'primitives') -----
> primitiveSoundStopRecording
> "Stop recording sound."
> + <export: true>
> + self snd_StopRecording!
> -
> - self primitive: 'primitiveSoundStopRecording'.
> - self cCode: 'snd_StopRecording()'. "leave rcvr on stack"!
>
> Item was changed:
> ----- Method: SoundPlugin>>primitiveSoundSupportsAEC (in category
> 'primitives') -----
> primitiveSoundSupportsAEC
> + "Answer if the OS/hardware supports echo-cancellation."
> + <export: true>
> - "Answer true if the OS/hardware supports echo-cancellation, and
> false otherwise."
> | result |
> + result := self snd_SupportsAEC.
> + interpreterProxy failed ifFalse:
> + [interpreterProxy methodReturnBool: result ~= 0]!
> - self primitive: 'primitiveSoundSupportsAEC'.
> - interpreterProxy failed ifFalse: [
> - result := self cCode: 'snd_SupportsAEC()'.
> - result == 0 ifTrue: [^interpreterProxy falseObject]
> ifFalse: [^interpreterProxy trueObject]
> - ].
> - !
>
> Item was changed:
> ----- Method: VMClass>>cCoerce:to: (in category 'memory access') -----
> cCoerce: value to: cTypeString
> + "Type coercion. For translation a cast will be emitted. When
> running in Smalltalk
> - "Type coercion. For translation a cast will be emmitted. When
> running in Smalltalk
> answer a suitable wrapper for correct indexing."
> <doNotGenerate>
> ^value
> ifNil: [value]
> ifNotNil: [value coerceTo: cTypeString sim: self]!
>
> Item was changed:
> ----- Method:
> VMPluginCodeGenerator>>shouldGenerateAsInterpreterProxySend: (in category
> 'utilities') -----
> shouldGenerateAsInterpreterProxySend: aSendNode
> "Answer if this send should be generated as interpreterProxy->foo
> or its moral equivalent (*).
> (*) since we now use function pointers declared in each external
> plugin we only indirect through
> interopreterProxy at plugin initialization. But we still have to
> find the set of sends a plugin uses."
> | selector |
> (aSendNode receiver isVariable and: ['interpreterProxy' =
> aSendNode receiver name]) ifFalse: [^false].
> selector := aSendNode selector.
> "baseHeaderSize, minSmallInteger et al are #defined in each VM's
> interp.h"
> (VMBasicConstants mostBasicConstantSelectors includes: selector)
> ifTrue: [^false].
> "Only include genuine InterpreterProxy methods, excluding things
> not understood
> + by InterpreterProxy and things in its initialize, private and
> simulation protocols."
> + ^(#(initialize private #'simulation only') includes:
> (InterpreterProxy compiledMethodAt: selector ifAbsent: [^false]) protocol)
> not!
> - by InterpreterProxy and things in its initialize and private
> protocols."
> - ^(#(initialize private) includes: (InterpreterProxy
> compiledMethodAt: selector ifAbsent: [^false]) protocol) not!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20200801/2844c1b8/attachment-0001.html>
More information about the Vm-dev
mailing list