'From Squeak2.9alpha of 13 June 2000 [latest update: #3399] on 3 February 2001 at 6:57:49 pm'! "Change Set: EvenMoreNamedPrims-ar Date: 3 February 2001 Author: Andreas Raab A pretty final set of named primitives for a variety of methods that were formerly using indexed primitives, including: * ADPCM codec primitives * Sound generation primitives * Misc string and bitmap primitives. The CS also cleans up the generation of VM support files, removing the need for e.g., 'sqGSMCodec.c' or 'sqOldSoundPrims.c' unless these primitives are really generated. "! Smalltalk renameClassNamed: #ADPCMPlugin as: #ADPCMCodecPlugin! InterpreterPlugin subclass: #ADPCMCodecPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Plugins'! InterpreterPlugin subclass: #MiscPrimitivePlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Plugins'! InterpreterPlugin subclass: #SoundGenerationPlugin instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'VMConstruction-Plugins'! !SoundGenerationPlugin commentStamp: 'ar 2/3/2001 15:34' prior: 0! This class is a stub for the directly generated primitives in AbstractSound and subclasses.! !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'ar 2/3/2001 15:50'! privateDecodeMono: count | delta step predictedDelta bit | self var: #stepSizeTable declareC: 'short int *stepSizeTable'. self var: #indexTable declareC: 'short int *indexTable'. self var: #samples declareC: 'short int *samples'. self var: #encodedBytes declareC: 'unsigned char *encodedBytes'. 1 to: count do: [:i | (i bitAnd: frameSizeMask) = 1 ifTrue: [ "start of frame; read frame header" predicted _ self nextBits: 16. predicted > 32767 ifTrue: [predicted _ predicted - 65536]. index _ self nextBits: 6. samples at: (sampleIndex _ sampleIndex + 1) put: predicted] ifFalse: [ delta _ self nextBits: bitsPerSample. step _ stepSizeTable at: index + 1. predictedDelta _ 0. bit _ deltaValueHighBit. [bit > 0] whileTrue: [ (delta bitAnd: bit) > 0 ifTrue: [predictedDelta _ predictedDelta + step]. step _ step bitShift: -1. bit _ bit bitShift: -1]. predictedDelta _ predictedDelta + step. (delta bitAnd: deltaSignMask) > 0 ifTrue: [predicted _ predicted - predictedDelta] ifFalse: [predicted _ predicted + predictedDelta]. predicted > 32767 ifTrue: [predicted _ 32767] ifFalse: [predicted < -32768 ifTrue: [predicted _ -32768]]. index _ index + (indexTable at: (delta bitAnd: deltaValueMask) + 1). index < 0 ifTrue: [index _ 0] ifFalse: [index > 88 ifTrue: [index _ 88]]. samples at: (sampleIndex _ sampleIndex + 1) put: predicted]]. ! ! !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'ar 2/3/2001 15:50'! privateDecodeStereo: count | predictedLeft predictedRight indexLeft indexRight deltaLeft deltaRight stepLeft stepRight predictedDeltaLeft predictedDeltaRight bit | self var: #stepSizeTable declareC: 'short int *stepSizeTable'. self var: #indexTable declareC: 'short int *indexTable'. self var: #samples declareC: 'short int *samples'. self var: #encodedBytes declareC: 'unsigned char *encodedBytes'. self var: #rightSamples declareC: 'short int *rightSamples'. self var: #predicted declareC: 'short int *predicted'. self var: #index declareC: 'short int *index'. "make local copies of decoder state variables" predictedLeft _ predicted at: 1. predictedRight _ predicted at: 2. indexLeft _ index at: 1. indexRight _ index at: 2. 1 to: count do: [:i | (i bitAnd: frameSizeMask) = 1 ifTrue: [ "start of frame; read frame header" predictedLeft _ self nextBits: 16. indexLeft _ self nextBits: 6. predictedRight _ self nextBits: 16. indexRight _ self nextBits: 6. predictedLeft > 32767 ifTrue: [predictedLeft _ predictedLeft - 65536]. predictedRight > 32767 ifTrue: [predictedRight _ predictedRight - 65536]. samples at: (sampleIndex _ sampleIndex + 1) put: predictedLeft. rightSamples at: sampleIndex put: predictedRight] ifFalse: [ deltaLeft _ self nextBits: bitsPerSample. deltaRight _ self nextBits: bitsPerSample. stepLeft _ stepSizeTable at: indexLeft + 1. stepRight _ stepSizeTable at: indexRight + 1. predictedDeltaLeft _ predictedDeltaRight _ 0. bit _ deltaValueHighBit. [bit > 0] whileTrue: [ (deltaLeft bitAnd: bit) > 0 ifTrue: [ predictedDeltaLeft _ predictedDeltaLeft + stepLeft]. (deltaRight bitAnd: bit) > 0 ifTrue: [ predictedDeltaRight _ predictedDeltaRight + stepRight]. stepLeft _ stepLeft bitShift: -1. stepRight _ stepRight bitShift: -1. bit _ bit bitShift: -1]. predictedDeltaLeft _ predictedDeltaLeft + stepLeft. predictedDeltaRight _ predictedDeltaRight + stepRight. (deltaLeft bitAnd: deltaSignMask) > 0 ifTrue: [predictedLeft _ predictedLeft - predictedDeltaLeft] ifFalse: [predictedLeft _ predictedLeft + predictedDeltaLeft]. (deltaRight bitAnd: deltaSignMask) > 0 ifTrue: [predictedRight _ predictedRight - predictedDeltaRight] ifFalse: [predictedRight _ predictedRight + predictedDeltaRight]. predictedLeft > 32767 ifTrue: [predictedLeft _ 32767] ifFalse: [predictedLeft < -32768 ifTrue: [predictedLeft _ -32768]]. predictedRight > 32767 ifTrue: [predictedRight _ 32767] ifFalse: [predictedRight < -32768 ifTrue: [predictedRight _ -32768]]. indexLeft _ indexLeft + (indexTable at: (deltaLeft bitAnd: deltaValueMask) + 1). indexLeft < 0 ifTrue: [indexLeft _ 0] ifFalse: [indexLeft > 88 ifTrue: [indexLeft _ 88]]. indexRight _ indexRight + (indexTable at: (deltaRight bitAnd: deltaValueMask) + 1). indexRight < 0 ifTrue: [indexRight _ 0] ifFalse: [indexRight > 88 ifTrue: [indexRight _ 88]]. samples at: (sampleIndex _ sampleIndex + 1) put: predictedLeft. rightSamples at: sampleIndex put: predictedRight]]. "save local copies of decoder state variables" predicted at: 1 put: predictedLeft. predicted at: 2 put: predictedRight. index at: 1 put: indexLeft. index at: 2 put: indexRight. ! ! !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'ar 2/3/2001 15:51'! privateEncodeMono: count | step sign diff delta predictedDelta bit p | self var: #stepSizeTable declareC: 'short int *stepSizeTable'. self var: #indexTable declareC: 'short int *indexTable'. self var: #samples declareC: 'short int *samples'. self var: #encodedBytes declareC: 'unsigned char *encodedBytes'. step _ stepSizeTable at: 1. 1 to: count do: [:i | (i bitAnd: frameSizeMask) = 1 ifTrue: [ predicted _ samples at: (sampleIndex _ sampleIndex + 1). (p _ predicted) < 0 ifTrue: [p _ p + 65536]. self nextBits: 16 put: p. i < count ifTrue: [ index _ self indexForDeltaFrom: predicted to: (samples at: sampleIndex + 1)]. self nextBits: 6 put: index. ] ifFalse: [ "compute sign and magnitude of difference from the predicted sample" sign _ 0. diff _ (samples at: (sampleIndex _ sampleIndex + 1)) - predicted. diff < 0 ifTrue: [ sign _ deltaSignMask. diff _ 0 - diff]. "Compute encoded delta and the difference that this will cause in the predicted sample value during decoding. Note that this code approximates: delta _ (4 * diff) / step. predictedDelta _ ((delta + 0.5) * step) / 4; but in the shift step bits are dropped. Thus, even if you have fast mul/div hardware you cannot use it since you would get slightly different bits what than the algorithm defines." delta _ 0. predictedDelta _ 0. bit _ deltaValueHighBit. [bit > 0] whileTrue: [ diff >= step ifTrue: [ delta _ delta + bit. predictedDelta _ predictedDelta + step. diff _ diff - step]. step _ step bitShift: -1. bit _ bit bitShift: -1]. predictedDelta _ predictedDelta + step. "compute and clamp new prediction" sign > 0 ifTrue: [predicted _ predicted - predictedDelta] ifFalse: [predicted _ predicted + predictedDelta]. predicted > 32767 ifTrue: [predicted _ 32767] ifFalse: [predicted < -32768 ifTrue: [predicted _ -32768]]. "compute new index and step values" index _ index + (indexTable at: delta + 1). index < 0 ifTrue: [index _ 0] ifFalse: [index > 88 ifTrue: [index _ 88]]. step _ stepSizeTable at: index + 1. "output encoded, signed delta" self nextBits: bitsPerSample put: (sign bitOr: delta)]]. bitPosition > 0 ifTrue: [ "flush the last output byte, if necessary" encodedBytes at: (byteIndex _ byteIndex + 1) put: currentByte]. ! ! !ADPCMCodec methodsFor: 'as yet unclassified' stamp: 'ar 2/3/2001 15:51'! privateEncodeStereo: count "not yet implemented" self inline: false. self success: false.! ! !ADPCMCodec class methodsFor: 'primitive generation' stamp: 'ar 2/3/2001 15:50'! translatedPrimitives "Answer a string containing the translated C code for my primitives." "Note: This code currently must be hand-edited to remove several methods that are inlined (thus not needed) but not pruned out by the ST-to-C translator." ^#( (ADPCMCodec privateDecodeMono:) (ADPCMCodec privateDecodeStereo:) (ADPCMCodec privateEncodeMono:) (ADPCMCodec privateEncodeStereo:) (ADPCMCodec indexForDeltaFrom:to:) (ADPCMCodec nextBits:) (ADPCMCodec nextBits:put:)) ! ! !ADPCMCodecPlugin class methodsFor: 'translation' stamp: 'ar 2/3/2001 18:34'! translateOn: cg inlining: inlineFlag to: fullName local: localFlag "ADPCMCodecPlugin translateLocally" | code | cg addClass: InterpreterPlugin. InterpreterPlugin declareCVarsIn: cg. cg addMethodsForPrimitives: ADPCMCodec translatedPrimitives. "now remove a few which will be inlined but not pruned" cg pruneMethods: #(indexForDeltaFrom:to: nextBits: nextBits:put:). code _ cg generateCodeStringForPrimitives. self storeString: code onFileNamed: fullName.! ! !AbstractSound class methodsFor: 'primitive generation' stamp: 'ar 2/3/2001 15:30'! translatedPrimitives ^#( (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:) (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:) (LoopedSampledSound mixSampleCount:into:startingAt:leftVol:rightVol:) (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:) (ReverbSound applyReverbTo:startingAt:count:) ). ! ! !Bitmap methodsFor: 'filing' stamp: 'ar 2/3/2001 16:11'! compress: bm toByteArray: ba "Store a run-coded compression of the receiver into the byteArray ba, and return the last index stored into. ba is assumed to be large enough. The encoding is as follows... S {N D}*. S is the size of the original bitmap, followed by run-coded pairs. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes" | size k word j lowByte eqBytes i | self var: #bm declareC: 'int *bm'. self var: #ba declareC: 'unsigned char *ba'. size _ bm size. i _ self encodeInt: size in: ba at: 1. k _ 1. [k <= size] whileTrue: [word _ bm at: k. lowByte _ word bitAnd: 16rFF. eqBytes _ ((word >> 8) bitAnd: 16rFF) = lowByte and: [((word >> 16) bitAnd: 16rFF) = lowByte and: [((word >> 24) bitAnd: 16rFF) = lowByte]]. j _ k. [j < size and: [word = (bm at: j+1)]] "scan for = words..." whileTrue: [j _ j+1]. j > k ifTrue: ["We have two or more = words, ending at j" eqBytes ifTrue: ["Actually words of = bytes" i _ self encodeInt: j-k+1*4+1 in: ba at: i. ba at: i put: lowByte. i _ i+1] ifFalse: [i _ self encodeInt: j-k+1*4+2 in: ba at: i. i _ self encodeBytesOf: word in: ba at: i]. k _ j+1] ifFalse: ["Check for word of 4 = bytes" eqBytes ifTrue: ["Note 1 word of 4 = bytes" i _ self encodeInt: 1*4+1 in: ba at: i. ba at: i put: lowByte. i _ i+1. k _ k + 1] ifFalse: ["Finally, check for junk" [j < size and: [(bm at: j) ~= (bm at: j+1)]] "scan for ~= words..." whileTrue: [j _ j+1]. j = size ifTrue: [j _ j + 1]. "We have one or more unmatching words, ending at j-1" i _ self encodeInt: j-k*4+3 in: ba at: i. k to: j-1 do: [:m | i _ self encodeBytesOf: (bm at: m) in: ba at: i]. k _ j]]]. ^ i - 1 "number of bytes actually stored" " Space check: | n rawBytes myBytes b | n _ rawBytes _ myBytes _ 0. Form allInstancesDo: [:f | f unhibernate. b _ f bits. n _ n + 1. rawBytes _ rawBytes + (b size*4). myBytes _ myBytes + (b compressToByteArray size). f hibernate]. Array with: n with: rawBytes with: myBytes ColorForms: (116 230324 160318 ) Forms: (113 1887808 1325055 ) Integerity check: Form allInstances do: [:f | f unhibernate. f bits = (Bitmap decompressFromByteArray: f bits compressToByteArray) ifFalse: [self halt]. f hibernate] Speed test: MessageTally spyOn: [Form allInstances do: [:f | Bitmap decompressFromByteArray: f bits compressToByteArray]] "! ! !Bitmap methodsFor: 'filing' stamp: 'ar 2/3/2001 16:11'! decompress: bm fromByteArray: ba at: index "Decompress the body of a byteArray encoded by compressToByteArray (qv)... The format is simply a sequence of run-coded pairs, {N D}*. N is a run-length * 4 + data code. D, the data, depends on the data code... 0 skip N words, D is absent (could be used to skip from one raster line to the next) 1 N words with all 4 bytes = D (1 byte) 2 N words all = D (4 bytes) 3 N words follow in D (4N bytes) S and N are encoded as follows (see decodeIntFrom:)... 0-223 0-223 224-254 (0-30)*256 + next byte (0-7935) 255 next 4 bytes" "NOTE: If fed with garbage, this routine could read past the end of ba, but it should fail before writing past the ned of bm." | i code n anInt data end k pastEnd | self var: #bm declareC: 'int *bm'. self var: #ba declareC: 'unsigned char *ba'. i _ index. "byteArray read index" end _ ba size. k _ 1. "bitmap write index" pastEnd _ bm size + 1. [i <= end] whileTrue: ["Decode next run start N" anInt _ ba at: i. i _ i+1. anInt <= 223 ifFalse: [anInt <= 254 ifTrue: [anInt _ (anInt-224)*256 + (ba at: i). i _ i+1] ifFalse: [anInt _ 0. 1 to: 4 do: [:j | anInt _ (anInt bitShift: 8) + (ba at: i). i _ i+1]]]. n _ anInt >> 2. (k + n) > pastEnd ifTrue: [^ self primitiveFail]. code _ anInt bitAnd: 3. code = 0 ifTrue: ["skip"]. code = 1 ifTrue: ["n consecutive words of 4 bytes = the following byte" data _ ba at: i. i _ i+1. data _ data bitOr: (data bitShift: 8). data _ data bitOr: (data bitShift: 16). 1 to: n do: [:j | bm at: k put: data. k _ k+1]]. code = 2 ifTrue: ["n consecutive words = 4 following bytes" data _ 0. 1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i). i _ i+1]. 1 to: n do: [:j | bm at: k put: data. k _ k+1]]. code = 3 ifTrue: ["n consecutive words from the data..." 1 to: n do: [:m | data _ 0. 1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i). i _ i+1]. bm at: k put: data. k _ k+1]]]! ! !FMSound methodsFor: 'sound generation' stamp: 'ar 2/3/2001 15:22'! mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol "Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy." "(FMSound pitch: 440.0 dur: 1.0 loudness: 0.5) play" | doingFM lastIndex sample offset i s | self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'. self var: #waveTable declareC: 'short int *waveTable'. doingFM _ (normalizedModulation ~= 0) and: [scaledOffsetIndexIncr ~= 0]. lastIndex _ (startIndex + n) - 1. startIndex to: lastIndex do: [:sliceIndex | sample _ (scaledVol * (waveTable at: (scaledIndex // ScaleFactor) + 1)) // ScaleFactor. doingFM ifTrue: [ offset _ normalizedModulation * (waveTable at: (scaledOffsetIndex // ScaleFactor) + 1). scaledOffsetIndex _ (scaledOffsetIndex + scaledOffsetIndexIncr) \\ scaledWaveTableSize. scaledOffsetIndex < 0 ifTrue: [scaledOffsetIndex _ scaledOffsetIndex + scaledWaveTableSize]. scaledIndex _ (scaledIndex + scaledIndexIncr + offset) \\ scaledWaveTableSize. scaledIndex < 0 ifTrue: [scaledIndex _ scaledIndex + scaledWaveTableSize]] ifFalse: [ scaledIndex _ (scaledIndex + scaledIndexIncr) \\ scaledWaveTableSize]. leftVol > 0 ifTrue: [ i _ (2 * sliceIndex) - 1. s _ (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. rightVol > 0 ifTrue: [ i _ 2 * sliceIndex. s _ (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. scaledVolIncr ~= 0 ifTrue: [ scaledVol _ scaledVol + scaledVolIncr. ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or: [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]]) ifTrue: [ "reached the limit; stop incrementing" scaledVol _ scaledVolLimit. scaledVolIncr _ 0]]]. count _ count - n. ! ! !Interpreter class methodsFor: 'initialization' stamp: 'ar 2/3/2001 16:22'! initializePrimitiveTable "This table generates a C switch statement for primitive dispatching." "NOTE: The real limit here is 2047, but our C compiler currently barfs over 700" MaxPrimitiveIndex _ 700. PrimitiveTable _ Array new: MaxPrimitiveIndex + 1. self table: PrimitiveTable from: #( "Integer Primitives (0-19)" (0 primitiveFail) (1 primitiveAdd) (2 primitiveSubtract) (3 primitiveLessThan) (4 primitiveGreaterThan) (5 primitiveLessOrEqual) (6 primitiveGreaterOrEqual) (7 primitiveEqual) (8 primitiveNotEqual) (9 primitiveMultiply) (10 primitiveDivide) (11 primitiveMod) (12 primitiveDiv) (13 primitiveQuo) (14 primitiveBitAnd) (15 primitiveBitOr) (16 primitiveBitXor) (17 primitiveBitShift) (18 primitiveMakePoint) (19 primitiveFail) "Guard primitive for simulation -- *must* fail" "LargeInteger Primitives (20-39)" "32-bit logic is aliased to Integer prims above" (20 39 primitiveFail) "Float Primitives (40-59)" (40 primitiveAsFloat) (41 primitiveFloatAdd) (42 primitiveFloatSubtract) (43 primitiveFloatLessThan) (44 primitiveFloatGreaterThan) (45 primitiveFloatLessOrEqual) (46 primitiveFloatGreaterOrEqual) (47 primitiveFloatEqual) (48 primitiveFloatNotEqual) (49 primitiveFloatMultiply) (50 primitiveFloatDivide) (51 primitiveTruncated) (52 primitiveFractionalPart) (53 primitiveExponent) (54 primitiveTimesTwoPower) (55 primitiveSquareRoot) (56 primitiveSine) (57 primitiveArctan) (58 primitiveLogN) (59 primitiveExp) "Subscript and Stream Primitives (60-67)" (60 primitiveAt) (61 primitiveAtPut) (62 primitiveSize) (63 primitiveStringAt) (64 primitiveStringAtPut) (65 primitiveNext) (66 primitiveNextPut) (67 primitiveAtEnd) "StorageManagement Primitives (68-79)" (68 primitiveObjectAt) (69 primitiveObjectAtPut) (70 primitiveNew) (71 primitiveNewWithArg) (72 primitiveArrayBecomeOneWay) "Blue Book: primitiveBecome" (73 primitiveInstVarAt) (74 primitiveInstVarAtPut) (75 primitiveAsOop) (76 primitiveStoreStackp) "Blue Book: primitiveAsObject" (77 primitiveSomeInstance) (78 primitiveNextInstance) (79 primitiveNewMethod) "Control Primitives (80-89)" (80 primitiveBlockCopy) (81 primitiveValue) (82 primitiveValueWithArgs) (83 primitivePerform) (84 primitivePerformWithArgs) (85 primitiveSignal) (86 primitiveWait) (87 primitiveResume) (88 primitiveSuspend) (89 primitiveFlushCache) "Input/Output Primitives (90-109)" (90 primitiveMousePoint) (91 primitiveTestDisplayDepth) "Blue Book: primitiveCursorLocPut" (92 primitiveSetDisplayMode) "Blue Book: primitiveCursorLink" (93 primitiveInputSemaphore) (94 primitiveGetNextEvent) "Blue Book: primitiveSampleInterval" (95 primitiveInputWord) (96 primitiveObsoleteIndexedPrimitive) "primitiveCopyBits" (97 primitiveSnapshot) (98 primitiveStoreImageSegment) (99 primitiveLoadImageSegment) (100 primitivePerformInSuperclass) "Blue Book: primitiveSignalAtTick" (101 primitiveBeCursor) (102 primitiveBeDisplay) (103 primitiveScanCharacters) (104 primitiveObsoleteIndexedPrimitive) "primitiveDrawLoop" (105 primitiveStringReplace) (106 primitiveScreenSize) (107 primitiveMouseButtons) (108 primitiveKbdNext) (109 primitiveKbdPeek) "System Primitives (110-119)" (110 primitiveEquivalent) (111 primitiveClass) (112 primitiveBytesLeft) (113 primitiveQuit) (114 primitiveExitToDebugger) (115 primitiveFail) "Blue Book: primitiveOopsLeft" (116 primitiveFlushCacheByMethod) (117 primitiveExternalCall) (118 primitiveDoPrimitiveWithArgs) (119 primitiveFlushCacheSelective) "Squeak 2.2 and earlier use 119. Squeak 2.3 and later use 116. Both are supported for backward compatibility." "Miscellaneous Primitives (120-127)" (120 primitiveCalloutToFFI) (121 primitiveImageName) (122 primitiveNoop) "Blue Book: primitiveImageVolume" (123 primitiveFail) (124 primitiveLowSpaceSemaphore) (125 primitiveSignalAtBytesLeft) "Squeak Primitives Start Here" "Squeak Miscellaneous Primitives (128-149)" (126 primitiveDeferDisplayUpdates) (127 primitiveShowDisplayRect) (128 primitiveArrayBecome) (129 primitiveSpecialObjectsOop) (130 primitiveFullGC) (131 primitiveIncrementalGC) (132 primitiveObjectPointsTo) (133 primitiveSetInterruptKey) (134 primitiveInterruptSemaphore) (135 primitiveMillisecondClock) (136 primitiveSignalAtMilliseconds) (137 primitiveSecondsClock) (138 primitiveSomeObject) (139 primitiveNextObject) (140 primitiveBeep) (141 primitiveClipboardText) (142 primitiveVMPath) (143 primitiveShortAt) (144 primitiveShortAtPut) (145 primitiveConstantFill) (146 primitiveObsoleteIndexedPrimitive) "primitiveReadJoystick" (147 primitiveObsoleteIndexedPrimitive) "primitiveWarpBits" (148 primitiveClone) (149 primitiveGetAttribute) "File Primitives (150-169) - NO LONGER INDEXED" (150 164 primitiveObsoleteIndexedPrimitive) (165 168 primitiveFail) (169 primitiveObsoleteIndexedPrimitive) "Sound Primitives (170-199) - NO LONGER INDEXED" (170 185 primitiveObsoleteIndexedPrimitive) (186 188 primitiveFail) (189 194 primitiveObsoleteIndexedPrimitive) (195 199 primitiveFail) "Networking Primitives (200-229) - NO LONGER INDEXED" (200 225 primitiveObsoleteIndexedPrimitive) (226 229 primitiveFail) "Other Primitives (230-249)" (230 primitiveRelinquishProcessor) (231 primitiveForceDisplayUpdate) (232 primitiveFormPrint) (233 primitiveSetFullScreen) (234 primitiveObsoleteIndexedPrimitive) "primBitmapdecompressfromByteArrayat" (235 primitiveObsoleteIndexedPrimitive) "primStringcomparewithcollated" (236 primitiveObsoleteIndexedPrimitive) "primSampledSoundconvert8bitSignedFromto16Bit" (237 primitiveObsoleteIndexedPrimitive) "primBitmapcompresstoByteArray" (238 241 primitiveObsoleteIndexedPrimitive) "serial port primitives" (242 primitiveFail) (243 primitiveObsoleteIndexedPrimitive) "primStringtranslatefromtotable" (244 primitiveObsoleteIndexedPrimitive) "primStringfindFirstInStringinSetstartingAt" (245 primitiveObsoleteIndexedPrimitive) "primStringindexOfAsciiinStringstartingAt" (246 primitiveObsoleteIndexedPrimitive) "primStringfindSubstringinstartingAtmatchTable" (247 primitiveSnapshotEmbedded) (248 249 primitiveFail) "VM Implementor Primitives (250-255)" (250 clearProfile) (251 dumpProfile) (252 startProfiling) (253 stopProfiling) (254 primitiveVMParameter) (255 primitiveInstVarsPutFromStack) "Never used except in Disney tests. Remove after 2.3 release." "Quick Push Const Methods" (256 primitivePushSelf) (257 primitivePushTrue) (258 primitivePushFalse) (259 primitivePushNil) (260 primitivePushMinusOne) (261 primitivePushZero) (262 primitivePushOne) (263 primitivePushTwo) "Quick Push Const Methods" (264 519 primitiveLoadInstVar) "MIDI Primitives (520-539) - NO LONGER INDEXED" (520 529 primitiveObsoleteIndexedPrimitive) (530 539 primitiveFail) "reserved for extended MIDI primitives" "Experimental Asynchrous File Primitives - NO LONGER INDEXED" (540 545 primitiveObsoleteIndexedPrimitive) (546 547 primitiveFail) "Pen Tablet Primitives - NO LONGER INDEXED" (548 primitiveObsoleteIndexedPrimitive) (549 primitiveObsoleteIndexedPrimitive) "Sound Codec Primitives - NO LONGER INDEXED" (550 553 primitiveObsoleteIndexedPrimitive) (554 569 primitiveFail) "External primitive support primitives" (570 primitiveFlushExternalPrimitives) (571 primitiveUnloadModule) (572 primitiveListBuiltinModule) (573 primitiveListExternalModule) (574 primitiveFail) "reserved for addl. external support prims" "Unassigned Primitives" (575 700 primitiveFail)). ! ! !Interpreter class methodsFor: 'initialization' stamp: 'ar 2/3/2001 16:22'! obsoleteIndexedPrimitiveTable "Interpreter obsoleteIndexedPrimitiveTableString" "Initialize the links from the (now obsolete) indexed primitives to the new named primitives." | table | table _ Array new: MaxPrimitiveIndex+1. #( (96 (BitBltPlugin primitiveCopyBits)) (104 (BitBltPlugin primitiveDrawLoop)) (147 (BitBltPlugin primitiveWarpBits)) (146 (JoystickTabletPlugin primitiveReadJoystick)) "File Primitives (150-169)" (150 (FilePlugin primitiveFileAtEnd)) (151 (FilePlugin primitiveFileClose)) (152 (FilePlugin primitiveFileGetPosition)) (153 (FilePlugin primitiveFileOpen)) (154 (FilePlugin primitiveFileRead)) (155 (FilePlugin primitiveFileSetPosition)) (156 (FilePlugin primitiveFileDelete)) (157 (FilePlugin primitiveFileSize)) (158 (FilePlugin primitiveFileWrite)) (159 (FilePlugin primitiveFileRename)) (160 (FilePlugin primitiveDirectoryCreate)) (161 (FilePlugin primitiveDirectoryDelimitor)) (162 (FilePlugin primitiveDirectoryLookup)) (163 (FilePlugin primitiveDirectoryDelete)) (164 (FilePlugin primitiveDirectoryGetMacTypeAndCreator)) (169 (FilePlugin primitiveDirectorySetMacTypeAndCreator)) "Sound Primitives (170-199)" (170 (SoundPlugin primitiveSoundStart)) (171 (SoundPlugin primitiveSoundStartWithSemaphore)) (172 (SoundPlugin primitiveSoundStop)) (173 (SoundPlugin primitiveSoundAvailableSpace)) (174 (SoundPlugin primitiveSoundPlaySamples)) (175 (SoundPlugin primitiveSoundPlaySilence)) (176 (SoundGenerationPlugin primitiveWaveTableSoundMix)) (177 (SoundGenerationPlugin primitiveFMSoundMix)) (178 (SoundGenerationPlugin primitivePluckedSoundMix)) (179 (SoundGenerationPlugin primitiveSampledSoundMix)) (180 (SoundGenerationPlugin primitiveMixFMSound)) (181 (SoundGenerationPlugin primitiveMixPluckedSound)) (182 (SoundGenerationPlugin primitiveOldSampledSoundMix)) (183 (SoundGenerationPlugin primitiveApplyReverb)) (184 (SoundGenerationPlugin primitiveMixLoopedSampledSound)) (185 (SoundGenerationPlugin primitiveMixSampledSound)) (189 (SoundPlugin primitiveSoundInsertSamples)) (190 (SoundPlugin primitiveSoundStartRecording)) (191 (SoundPlugin primitiveSoundStopRecording)) (192 (SoundPlugin primitiveSoundGetRecordingSampleRate)) (193 (SoundPlugin primitiveSoundRecordSamples)) (194 (SoundPlugin primitiveSoundSetRecordLevel)) "Networking Primitives (200-229)" (200 (SocketPlugin primitiveInitializeNetwork)) (201 (SocketPlugin primitiveResolverStartNameLookup)) (202 (SocketPlugin primitiveResolverNameLookupResult)) (203 (SocketPlugin primitiveResolverStartAddressLookup)) (204 (SocketPlugin primitiveResolverAddressLookupResult)) (205 (SocketPlugin primitiveResolverAbortLookup)) (206 (SocketPlugin primitiveResolverLocalAddress)) (207 (SocketPlugin primitiveResolverStatus)) (208 (SocketPlugin primitiveResolverError)) (209 (SocketPlugin primitiveSocketCreate)) (210 (SocketPlugin primitiveSocketDestroy)) (211 (SocketPlugin primitiveSocketConnectionStatus)) (212 (SocketPlugin primitiveSocketError)) (213 (SocketPlugin primitiveSocketLocalAddress)) (214 (SocketPlugin primitiveSocketLocalPort)) (215 (SocketPlugin primitiveSocketRemoteAddress)) (216 (SocketPlugin primitiveSocketRemotePort)) (217 (SocketPlugin primitiveSocketConnectToPort)) (218 (SocketPlugin primitiveSocketListenWithOrWithoutBacklog)) (219 (SocketPlugin primitiveSocketCloseConnection)) (220 (SocketPlugin primitiveSocketAbortConnection)) (221 (SocketPlugin primitiveSocketReceiveDataBufCount)) (222 (SocketPlugin primitiveSocketReceiveDataAvailable)) (223 (SocketPlugin primitiveSocketSendDataBufCount)) (224 (SocketPlugin primitiveSocketSendDone)) (225 (SocketPlugin primitiveSocketAccept)) "Other Primitives (230-249)" (234 (MiscPrimitivePlugin primitiveDecompressFromByteArray)) (235 (MiscPrimitivePlugin primitiveCompareString)) (236 (MiscPrimitivePlugin primitiveConvert8BitSigned)) (237 (MiscPrimitivePlugin primitiveCompressToByteArray)) (238 (SerialPlugin primitiveSerialPortOpen)) (239 (SerialPlugin primitiveSerialPortClose)) (240 (SerialPlugin primitiveSerialPortWrite)) (241 (SerialPlugin primitiveSerialPortRead)) (243 (MiscPrimitivePlugin primitiveTranslateStringWithTable)) (244 (MiscPrimitivePlugin primitiveFindFirstInString)) (245 (MiscPrimitivePlugin primitiveIndexOfAsciiInString)) (246 (MiscPrimitivePlugin primitiveFindSubstring)) "MIDI Primitives (520-539)" (521 (MIDIPlugin primitiveMIDIClosePort)) (522 (MIDIPlugin primitiveMIDIGetClock)) (523 (MIDIPlugin primitiveMIDIGetPortCount)) (524 (MIDIPlugin primitiveMIDIGetPortDirectionality)) (525 (MIDIPlugin primitiveMIDIGetPortName)) (526 (MIDIPlugin primitiveMIDIOpenPort)) (527 (MIDIPlugin primitiveMIDIParameterGetOrSet)) (528 (MIDIPlugin primitiveMIDIRead)) (529 (MIDIPlugin primitiveMIDIWrite)) "Experimental Asynchrous File Primitives" (540 (AsynchFilePlugin primitiveAsyncFileClose)) (541 (AsynchFilePlugin primitiveAsyncFileOpen)) (542 (AsynchFilePlugin primitiveAsyncFileReadResult)) (543 (AsynchFilePlugin primitiveAsyncFileReadStart)) (544 (AsynchFilePlugin primitiveAsyncFileWriteResult)) (545 (AsynchFilePlugin primitiveAsyncFileWriteStart)) "Pen Tablet Primitives" (548 (JoystickTabletPlugin primitiveGetTabletParameters)) (549 (JoystickTabletPlugin primitiveReadTablet)) "Sound Codec Primitives" (550 (ADPCMCodecPlugin primitiveDecodeMono)) (551 (ADPCMCodecPlugin primitiveDecodeStereo)) (552 (ADPCMCodecPlugin primitiveEncodeMono)) (553 (ADPCMCodecPlugin primitiveEncodeStereo)) ) do:[:spec| table at: spec first+1 put: spec second]. ^table! ! !Interpreter class methodsFor: 'translation' stamp: 'ar 2/3/2001 18:20'! translate: fileName doInlining: inlineFlag forBrowserPlugin: pluginFlag "Note: The pluginFlag is meaningless on Windows and Unix. On these platforms Squeak runs as it's own process and doesn't need any special attention from the VMs point of view. Meaning that NONE of the required additional functions will be supported. In other words, the pluginFlag is not needed and not supported." "Translate the Smalltalk description of the virtual machine into C. If inlineFlag is true, small method bodies are inlined to reduce procedure call overhead. On the PPC, this results in a factor of three speedup with only 30% increase in code size. If pluginFlag is true, generate code for an interpreter that runs as a browser plugin (Netscape or IE)." | doInlining cg exports | doInlining _ inlineFlag. pluginFlag ifTrue: [doInlining _ true]. "must inline when generating browser plugin" Interpreter initialize. ObjectMemory initialize. GenerateBrowserPlugin _ pluginFlag. cg _ CCodeGenerator new initialize. cg addClass: Interpreter. cg addClass: ObjectMemory. Interpreter declareCVarsIn: cg. ObjectMemory declareCVarsIn: cg. "Get all the named prims from the VM. Note: the format of exports is: pluginName -> Array of: primitiveName. so we can generate a nice table from it." exports _ Array with: '' -> cg exportedPrimitiveNames asArray. cg storeCodeOnFile: fileName doInlining: doInlining. "Add our plugins" { "Graphics" "Note: BitBltSimulation should go first, because three of it's entries might be looked up quite often (due to refs from InterpreterProxy). This will go away at some point but for now it's a good idea to have those entries early in the table." BitBltSimulation. BalloonEnginePlugin. SurfacePlugin. "To support OS surfaces through FXBlt" "I/O subsystems" FilePlugin. SocketPlugin. MIDIPlugin. SerialPlugin. JoystickTabletPlugin. AsynchFilePlugin. "Sound" SoundPlugin. SoundGenerationPlugin. ADPCMCodecPlugin. KlattSynthesizerPlugin. SoundCodecPlugin. "Numerics" LargeIntegersPlugin. FFTPlugin. FloatArrayPlugin. Matrix2x3Plugin. "Compression" DeflatePlugin. "Others" B3DEnginePlugin. DSAPlugin. DropPlugin. MiscPrimitivePlugin. "Note: Optionally, you can translate the following as builtins. As of Squeak 2.7 they are not builtins by default: FFIPlugin. " } do:[:plugin| cg _ plugin translate: plugin moduleName, '.c' doInlining: doInlining locally: true. exports _ exports copyWith: (plugin moduleName -> cg exportedPrimitiveNames asArray). ]. self storeExports: exports on: 'sqNamedPrims.h'.! ! !InterpreterSupportCode class methodsFor: 'source file exporting' stamp: 'ar 2/3/2001 16:33'! compareWithFilesInFolder: folderName "InterpreterSupportCode compareWithFilesInFolder: 'Tosh:Desktop Folder:Squeak VM Project'" | dir | dir _ FileDirectory on: folderName. (dir readOnlyFileNamed: 'projectArchive.sit') binary contentsOfEntireFile = InterpreterSupportCode macArchiveBinaryFile asByteArray ifFalse: [self inform: 'File projectArchive.sit differs from the version stored in this image.']. (dir readOnlyFileNamed: 'readme') contentsOfEntireFile = InterpreterSupportCode readmeFile ifFalse: [self inform: 'File readme differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sq.h') contentsOfEntireFile = InterpreterSupportCode squeakHeaderFile ifFalse: [self inform: 'File sq.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqConfig.h') contentsOfEntireFile = InterpreterSupportCode squeakConfigFile ifFalse: [self inform: 'File sqConfig.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'platform.exports') contentsOfEntireFile = InterpreterSupportCode squeakPlatformExportsFile ifFalse: [self inform: 'File platform.exports differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqPlatformSpecific.h') contentsOfEntireFile = InterpreterSupportCode squeakPlatSpecFile ifFalse: [self inform: 'File sqPlatformSpecific.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqFilePrims.c') contentsOfEntireFile = InterpreterSupportCode squeakFilePrimsFile ifFalse: [self inform: 'File sqFilePrims.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacAsyncFilePrims.c') contentsOfEntireFile = InterpreterSupportCode macAsyncFilePrimsFile ifFalse: [self inform: 'File sqMacAsyncFilePrims.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacNSPlugin.c') contentsOfEntireFile = InterpreterSupportCode macBrowserPluginFile ifFalse: [self inform: 'File sqMacNSPlugin.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacDirectory.c') contentsOfEntireFile = InterpreterSupportCode macDirectoryFile ifFalse: [self inform: 'File sqMacDirectory.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacDragDrop.c') contentsOfEntireFile = InterpreterSupportCode macDragDropFile ifFalse: [self inform: 'File sqMacDragDrop.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacJoystickAndTablet.c') contentsOfEntireFile = InterpreterSupportCode macJoystickAndTabletFile ifFalse: [self inform: 'File sqMacJoystickAndTablet.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacMinimal.c') contentsOfEntireFile = InterpreterSupportCode macMinimal ifFalse: [self inform: 'File sqMacMinimal.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacNetwork.c') contentsOfEntireFile = InterpreterSupportCode macNetworkFile ifFalse: [self inform: 'File sqMacNetwork.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacSerialAndMIDIPort.c') contentsOfEntireFile = InterpreterSupportCode macSerialAndMIDIPortFile ifFalse: [self inform: 'File sqMacSerialAndMIDIPort.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacSound.c') contentsOfEntireFile = InterpreterSupportCode macSoundFile ifFalse: [self inform: 'File sqMacSound.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqMacWindow.c') contentsOfEntireFile = InterpreterSupportCode macWindowFile ifFalse: [self inform: 'File sqMacWindow.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqNamedPrims.c') contentsOfEntireFile = InterpreterSupportCode squeakNamedPrimsFile ifFalse: [self inform: 'File sqNamedPrims.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqVirtualMachine.h') contentsOfEntireFile = InterpreterSupportCode squeakVirtualMachineHeaderFile ifFalse: [self inform: 'File sqVirtualMachine.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'sqVirtualMachine.c') contentsOfEntireFile = InterpreterSupportCode squeakVirtualMachineFile ifFalse: [self inform: 'File sqVirtualMachine.c differs from the version stored in this image.']. (dir readOnlyFileNamed: 'MacTCP.h') contentsOfEntireFile = InterpreterSupportCode macTCPFile ifFalse: [self inform: 'File MacTCP.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'AddressXlation.h') contentsOfEntireFile = InterpreterSupportCode macAddressXlationFile ifFalse: [self inform: 'File AddressXlation.h differs from the version stored in this image.']. (dir readOnlyFileNamed: 'dnr.c') contentsOfEntireFile = InterpreterSupportCode macDNRFile ifFalse: [self inform: 'File dnr.c differs from the version stored in this image.']. ! ! !InterpreterSupportCode class methodsFor: 'source file exporting' stamp: 'ar 2/3/2001 16:33'! writeSupportFiles "Store into this image's folder the C sources files required to support the interpreter on all platforms. This method also generates the code for the sound synthesis and other primitives translated from Smalltalk to C. However, because generating code for the interpreter itself takes several minutes, that is not done automatically by this method. To generate that code, use the method 'translate:doInlining:' in Interpreter class." "InterpreterSupportCode writeSupportFiles" self storeString: self readmeFile onFileNamed: 'readme'. self storeString: self squeakHeaderFile onFileNamed: 'sq.h'. self storeString: self squeakConfigFile onFileNamed: 'sqConfig.h'. self storeString: self squeakPlatformExportsFile onFileNamed: 'platform.exports'. self storeString: self squeakPlatSpecFile onFileNamed: 'sqPlatformSpecific.h'. self storeString: self squeakVirtualMachineHeaderFile onFileNamed: 'sqVirtualMachine.h'. self storeString: self squeakVirtualMachineFile onFileNamed: 'sqVirtualMachine.c'. self storeString: self squeakNamedPrimsFile onFileNamed:'sqNamedPrims.c'. self storeString: self squeakFilePrimsFile onFileNamed: 'sqFilePrims.c'.! ! !InterpreterSupportCode class methodsFor: 'source files' stamp: 'ar 2/3/2001 16:35'! squeakHeaderFile ^'#include #include #include #include #include #include "sqConfig.h" #include "sqVirtualMachine.h" #define true 1 #define false 0 #define null 0 /* using "null" because nil is predefined in Think C */ /* pluggable primitives macros */ /* Note: All pluggable primitives are defined as EXPORT(int) somePrimitive(void) If the platform requires special declaration modifiers the EXPORT macro can be redefined */ #define EXPORT(returnType) returnType /* image save/restore macros */ /* Note: The image file save and restore code uses these macros; they can be redefined in sqPlatformSpecific.h if desired. These default versions are defined in terms of the ANSI Standard C libraries. */ #define sqImageFile FILE * #define sqImageFileClose(f) fclose(f) #define sqImageFileOpen(fileName, mode) fopen(fileName, mode) #define sqImageFilePosition(f) ftell(f) #define sqImageFileRead(ptr, sz, count, f) fread(ptr, sz, count, f) #define sqImageFileSeek(f, pos) fseek(f, pos, SEEK_SET) #define sqImageFileWrite(ptr, sz, count, f) fwrite(ptr, sz, count, f) #define sqImageFileStartLocation(fileRef, fileName, size) 0 #define sqAllocateMemory(minHeapSize, desiredHeapSize) malloc(desiredHeapSize) /* platform-dependent float conversion macros */ /* Note: Second argument must be a variable name, not an expression!! */ /* Note: Floats in image are always in PowerPC word order; change these macros to swap words if necessary. This costs no extra and obviates sometimes having to word-swap floats when reading an image. */ #if defined(DOUBLE_WORD_ALIGNMENT) || defined(DOUBLE_WORD_ORDER) # ifdef DOUBLE_WORD_ORDER /* word-based copy with swapping for non-PowerPC order */ # define storeFloatAtfrom(i, floatVarName) \ *((int *) (i) + 0) = *((int *) &(floatVarName) + 1); \ *((int *) (i) + 1) = *((int *) &(floatVarName) + 0); # define fetchFloatAtinto(i, floatVarName) \ *((int *) &(floatVarName) + 0) = *((int *) (i) + 1); \ *((int *) &(floatVarName) + 1) = *((int *) (i) + 0); # else /*!!DOUBLE_WORD_ORDER*/ /* word-based copy for machines with alignment restrictions */ # define storeFloatAtfrom(i, floatVarName) \ *((int *) (i) + 0) = *((int *) &(floatVarName) + 0); \ *((int *) (i) + 1) = *((int *) &(floatVarName) + 1); # define fetchFloatAtinto(i, floatVarName) \ *((int *) &(floatVarName) + 0) = *((int *) (i) + 0); \ *((int *) &(floatVarName) + 1) = *((int *) (i) + 1); # endif /*!!DOUBLE_WORD_ORDER*/ #else /*!!(DOUBLE_WORD_ORDER||DOUBLE_WORD_ALIGNMENT)*/ /* for machines that allow doubles to be on any word boundary */ # define storeFloatAtfrom(i, floatVarName) \ *((double *) (i)) = (floatVarName); # define fetchFloatAtinto(i, floatVarName) \ (floatVarName) = *((double *) (i)); #endif /* platform-dependent memory size adjustment macro */ /* Note: This macro can be redefined to allows platforms with a fixed application memory partition (notably, the Macintosh) to reserve extra C heap memory for special applications that need it (e.g., for a 3D graphics library). Since most platforms can extend their application memory partition at run time if needed, this macro is defined as a noop here and redefined if necessary in sqPlatformSpecific.h. */ #define reserveExtraCHeapBytes(origHeapSize, bytesToReserve) origHeapSize /* platform-dependent millisecond clock macros */ /* Note: The Squeak VM uses three different clocks functions for timing. The primary one, ioMSecs(), is used to implement Delay and Time millisecondClockValue. The resolution of this clock determines the resolution of these basic timing functions. For doing real-time control of music and MIDI, a clock with resolution down to one millisecond is preferred, but a coarser clock (say, 1/60th second) can be used in a pinch. The VM calls a different clock function, ioLowResMSecs(), in order to detect long-running primitives. This function must be inexpensive to call because when a Delay is active it is polled twice per primitive call. On several platforms (Mac, Win32), the high-resolution system clock used in ioMSecs() would incur enough overhead in this case to slow down the the VM significantly. Thus, a cheaper clock with low resolution is used to implement ioLowResMSecs() on these platforms. Finally, the function ioMicroMSecs() is used only to collect timing statistics for the garbage collector and other VM facilities. (The function name is meant to suggest that the function is based on a clock with microsecond accuracy, even though the times it returns are in units of milliseconds.) This clock must have enough precision to provide accurate timings, and normally isn''t called frequently enough to slow down the VM. Thus, it can use a more expensive clock that ioMSecs(). By default, all three clock functions are defined here as macros based on the standard C library function clock(). Any of these macros can be overridden in sqPlatformSpecific.h. */ int ioMSecs(void); int ioLowResMSecs(void); int ioMicroMSecs(void); #define ioMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) #define ioLowResMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) #define ioMicroMSecs() ((1000 * clock()) / CLOCKS_PER_SEC) /* filename copy/transform macro. An opportunity to transform the filenames for platforms with strange needs, anda simple encapsulation for everyone else */ #define sqFilenameFromString(dst, src, num) \ if (1) { \ int i; \ for (i = 0; i < num; i++) { \ dst[i] = *((char *) (src + i)); \ } \ dst[num] = 0;\ } /* this include file may redefine earlier definitions and macros: */ #include "sqPlatformSpecific.h" /* interpreter entry points */ void error(char *s); int checkedByteAt(int byteAddress); int checkedByteAtput(int byteAddress, int byte); int checkedLongAt(int byteAddress); int checkedLongAtput(int byteAddress, int a32BitInteger); int fullDisplayUpdate(void); int initializeInterpreter(int bytesToShift); int interpret(void); int primitiveFail(void); int signalSemaphoreWithIndex(int index); int success(int); /* display, mouse, keyboard, time i/o */ int ioBeep(void); int ioExit(void); int ioForceDisplayUpdate(void); int ioFormPrint( int bitsAddr, int width, int height, int depth, double hScale, double vScale, int landscapeFlag); int ioSetFullScreen(int fullScreen); int ioRelinquishProcessorForMicroseconds(int microSeconds); int ioScreenSize(void); int ioSeconds(void); int ioSetCursor(int cursorBitsIndex, int offsetX, int offsetY); int ioSetCursorWithMask(int cursorBitsIndex, int cursorMaskIndex, int offsetX, int offsetY); int ioShowDisplay( int dispBitsIndex, int width, int height, int depth, int affectedL, int affectedR, int affectedT, int affectedB); int ioHasDisplayDepth(int depth); int ioSetDisplayMode(int width, int height, int depth, int fullscreenFlag); /* Power Management */ int ioDisablePowerManager(int disableIfNonZero); /* User input recording I: In general, either set of input function can be supported, depending on the platform. This (first) set is state based and should be supported even on platforms that make use of the newer event driven API to support older images without event support. */ int ioGetButtonState(void); int ioGetKeystroke(void); int ioMousePoint(void); int ioPeekKeystroke(void); /* Note: In an event driven architecture, ioProcessEvents is obsolete. It can be implemented as a no-op since the image will check for events in regular intervals. */ int ioProcessEvents(void); /* User input recording II: The following functions and definition can be used on platform supporting events directly. */ /* types of events */ #define EventTypeNone 0 #define EventTypeMouse 1 #define EventTypeKeyboard 2 #define EventTypeDragDropFiles 3 /* keypress state for keyboard events */ #define EventKeyChar 0 #define EventKeyDown 1 #define EventKeyUp 2 /* button definitions */ #define RedButtonBit 4 #define BlueButtonBit 2 #define YellowButtonBit 1 /* modifier definitions */ #define ShiftKeyBit 1 #define CtrlKeyBit 2 #define OptionKeyBit 4 #define CommandKeyBit 8 /* generic input event definition */ typedef struct sqInputEvent { int type; /* type of event; either one of EventTypeXXX */ unsigned int timeStamp; /* time stamp */ /* the interpretation of the following fields depend on the type of the event */ int unused1; int unused2; int unused3; int unused4; int unused5; int unused6; } sqInputEvent; /* mouse input event definition */ typedef struct sqMouseEvent { int type; /* EventTypeMouse */ unsigned int timeStamp; /* time stamp */ int x; /* mouse position x */ int y; /* mouse position y */ int buttons; /* combination of xxxButtonBit */ int modifiers; /* combination of xxxKeyBit */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ } sqMouseEvent; /* keyboard input event definition */ typedef struct sqKeyboardEvent { int type; /* EventTypeKeyboard */ unsigned int timeStamp; /* time stamp */ int charCode; /* character code in Mac Roman encoding */ int pressCode; /* press code; any of EventKeyXXX */ int modifiers; /* combination of xxxKeyBit */ int reserved1; /* reserved for future use */ int reserved2; /* reserved for future use */ int reserved3; /* reserved for future use */ } sqKeyboardEvent; /* drop files event definition: DragEnter - drag operation from OS entered Squeak window DragMove - drag operation from OS moved within Squeak window DragLeave - drag operation from OS left Squeak window DragDrop - drag operation dropped contents onto Squeak. */ #define DragEnter 1 #define DragMove 2 #define DragLeave 3 #define DragDrop 4 typedef struct sqDragDropFilesEvent { int type; /* EventTypeDropFiles */ unsigned int timeStamp; /* time stamp */ int dragType; /* one of the DragXXX constants */ int x; /* mouse position x */ int y; /* mouse position y */ int modifiers; /* combination of xxxKeyBit */ int numFiles; /* number of files in transaction */ int reserved1; /* reserved for future use */ } sqDragDropFilesEvent; /* set an asynchronous input semaphore index for events */ int ioSetInputSemaphore(int semaIndex); /* retrieve the next input event from the OS */ int ioGetNextEvent(sqInputEvent *evt); /* image file and VM path names */ extern char imageName[]; int imageNameGetLength(int sqImageNameIndex, int length); int imageNamePutLength(int sqImageNameIndex, int length); int imageNameSize(void); int vmPathSize(void); int vmPathGetLength(int sqVMPathIndex, int length); /* save/restore */ /* Read the image from the given file starting at the given image offset */ int readImageFromFileHeapSizeStartingAt(sqImageFile f, int desiredHeapSize, int imageOffset); /* NOTE: The following is obsolete - it is only provided for compatibility */ #define readImageFromFileHeapSize(f, s) readImageFromFileHeapSizeStartingAt(f,s,0) /* clipboard (cut/copy/paste) */ int clipboardSize(void); int clipboardReadIntoAt(int count, int byteArrayIndex, int startIndex); int clipboardWriteFromAt(int count, int byteArrayIndex, int startIndex); /* browser plug-in support */ int plugInAllowAccessToFilePath(char *pathString, int pathStringLength); void plugInForceTimeToReturn(void); int plugInInit(char *imageName); int plugInNotifyUser(char *msg); void plugInSetStartTime(void); int plugInShutdown(void); int plugInTimeToReturn(void); /* interpreter entry points needed by compiled primitives */ void * arrayValueOf(int arrayOop); int checkedIntegerValueOf(int intOop); void * fetchArrayofObject(int fieldIndex, int objectPointer); double fetchFloatofObject(int fieldIndex, int objectPointer); int fetchIntegerofObject(int fieldIndex, int objectPointer); double floatValueOf(int floatOop); int pop(int nItems); int pushInteger(int integerValue); int sizeOfSTArrayFromCPrimitive(void *cPtr); int storeIntegerofObjectwithValue(int fieldIndex, int objectPointer, int integerValue); /* profiling */ int clearProfile(void); int dumpProfile(void); int startProfiling(void); int stopProfiling(void); /* system attributes */ int attributeSize(int id); int getAttributeIntoLength(int id, int byteArrayIndex, int length); /*** pluggable primitive support ***/ /* NOTE: The following functions are those implemented by sqNamedPrims.c */ int ioLoadExternalFunctionOfLengthFromModuleOfLength( int functionNameIndex, int functionNameLength, int moduleNameIndex, int moduleNameLength); int ioUnloadModuleOfLength(int moduleNameIndex, int moduleNameLength); int ioLoadFunctionFrom(char *functionName, char *pluginName); int ioShutdownAllModules(void); int ioUnloadModule(char *); int ioUnloadModuleOfLength(int moduleNameIndex, int moduleNameLength); char *ioListBuiltinModule(int moduleIndex); char *ioListLoadedModule(int moduleIndex); /* The next two are FFI entries!! (implemented in sqNamedPrims.c as well) */ int ioLoadModuleOfLength(int moduleNameIndex, int moduleNameLength); int ioLoadSymbolOfLengthFromModule(int functionNameIndex, int functionNameLength, int moduleHandle); /* The next three functions must be implemented by sqXYZExternalPrims.c */ /* ioLoadModule: Load a module from disk. WARNING: this always loads a *new* module. Don''t even attempt to find a loaded one. WARNING: never primitiveFail() within, just return 0 */ int ioLoadModule(char *pluginName); /* ioFindExternalFunctionIn: Find the function with the given name in the moduleHandle. WARNING: never primitiveFail() within, just return 0. */ int ioFindExternalFunctionIn(char *lookupName, int moduleHandle); /* ioFreeModule: Free the module with the associated handle. WARNING: never primitiveFail() within, just return 0. */ int ioFreeModule(int moduleHandle); /* The Squeak version this interpreter was generated from */ extern const char *interpreterVersion; '! ! !LoopedSampledSound methodsFor: 'sound generation' stamp: 'ar 2/3/2001 15:23'! mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol "Play samples from a wave table by stepping a fixed amount through the table on every sample. The table index and increment are scaled to allow fractional increments for greater pitch accuracy. If a loop length is specified, then the index is looped back when the loopEnd index is reached until count drops below releaseCount. This allows a short sampled sound to be sustained indefinitely." "(LoopedSampledSound pitch: 440.0 dur: 5.0 loudness: 0.5) play" | lastIndex sampleIndex i s compositeLeftVol compositeRightVol nextSampleIndex m isInStereo rightVal leftVal | self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'. self var: #leftSamples declareC: 'short int *leftSamples'. self var: #rightSamples declareC: 'short int *rightSamples'. isInStereo _ leftSamples ~~ rightSamples. compositeLeftVol _ (leftVol * scaledVol) // ScaleFactor. compositeRightVol _ (rightVol * scaledVol) // ScaleFactor. i _ (2 * startIndex) - 1. lastIndex _ (startIndex + n) - 1. startIndex to: lastIndex do: [:sliceIndex | sampleIndex _ (scaledIndex _ scaledIndex + scaledIndexIncr) // LoopIndexScaleFactor. ((sampleIndex > loopEnd) and: [count > releaseCount]) ifTrue: [ "loop back if not within releaseCount of the note end" "note: unlooped sounds will have loopEnd = lastSample" sampleIndex _ (scaledIndex _ scaledIndex - scaledLoopLength) // LoopIndexScaleFactor]. (nextSampleIndex _ sampleIndex + 1) > lastSample ifTrue: [ sampleIndex > lastSample ifTrue: [count _ 0. ^ nil]. "done!!" scaledLoopLength = 0 ifTrue: [nextSampleIndex _ sampleIndex] ifFalse: [nextSampleIndex _ ((scaledIndex - scaledLoopLength) // LoopIndexScaleFactor) + 1]]. m _ scaledIndex bitAnd: LoopIndexFractionMask. rightVal _ leftVal _ (((leftSamples at: sampleIndex) * (LoopIndexScaleFactor - m)) + ((leftSamples at: nextSampleIndex) * m)) // LoopIndexScaleFactor. isInStereo ifTrue: [ rightVal _ (((rightSamples at: sampleIndex) * (LoopIndexScaleFactor - m)) + ((rightSamples at: nextSampleIndex) * m)) // LoopIndexScaleFactor]. leftVol > 0 ifTrue: [ s _ (aSoundBuffer at: i) + ((compositeLeftVol * leftVal) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. i _ i + 1. rightVol > 0 ifTrue: [ s _ (aSoundBuffer at: i) + ((compositeRightVol * rightVal) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. i _ i + 1. scaledVolIncr ~= 0 ifTrue: [ "update volume envelope if it is changing" scaledVol _ scaledVol + scaledVolIncr. ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or: [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]]) ifTrue: [ "reached the limit; stop incrementing" scaledVol _ scaledVolLimit. scaledVolIncr _ 0]. compositeLeftVol _ (leftVol * scaledVol) // ScaleFactor. compositeRightVol _ (rightVol * scaledVol) // ScaleFactor]]. count _ count - n. ! ! !MiscPrimitivePlugin class methodsFor: 'translation' stamp: 'ar 2/3/2001 17:21'! translateOn: cg inlining: inlineFlag to: fullName local: localFlag "MiscPrimitivePlugin translateLocally" | code | code _ cg codeStringForPrimitives: self translatedPrimitives. self storeString: code onFileNamed: fullName.! ! !MiscPrimitivePlugin class methodsFor: 'translation' stamp: 'ar 2/3/2001 16:14'! translatedPrimitives "an assorted list of various primitives" ^#( (Bitmap compress:toByteArray:) (Bitmap decompress:fromByteArray:at:) (Bitmap encodeBytesOf:in:at:) (Bitmap encodeInt:in:at:) (String compare:with:collated:) (String translate:from:to:table:) (String findFirstInString:inSet:startingAt:) (String indexOfAscii:inString:startingAt:) (String findSubstring:in:startingAt:matchTable:) (SampledSound convert8bitSignedFrom:to16Bit:) ) ! ! !PluckedSound methodsFor: 'sound generation' stamp: 'ar 2/3/2001 15:23'! mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol "The Karplus-Strong plucked string algorithm: start with a buffer full of random noise and repeatedly play the contents of that buffer while averaging adjacent samples. High harmonics damp out more quickly, transfering their energy to lower ones. The length of the buffer corresponds to the length of the string." "(PluckedSound pitch: 220.0 dur: 6.0 loudness: 0.8) play" | lastIndex scaledThisIndex scaledNextIndex average sample i s | self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'. self var: #ring declareC: 'short int *ring'. lastIndex _ (startIndex + n) - 1. scaledThisIndex _ scaledNextIndex _ scaledIndex. startIndex to: lastIndex do: [:sliceIndex | scaledNextIndex _ scaledThisIndex + scaledIndexIncr. scaledNextIndex >= scaledIndexLimit ifTrue: [scaledNextIndex _ ScaleFactor + (scaledNextIndex - scaledIndexLimit)]. average _ ((ring at: scaledThisIndex // ScaleFactor) + (ring at: scaledNextIndex // ScaleFactor)) // 2. ring at: scaledThisIndex // ScaleFactor put: average. sample _ (average * scaledVol) // ScaleFactor. "scale by volume" scaledThisIndex _ scaledNextIndex. leftVol > 0 ifTrue: [ i _ (2 * sliceIndex) - 1. s _ (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. rightVol > 0 ifTrue: [ i _ 2 * sliceIndex. s _ (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. scaledVolIncr ~= 0 ifTrue: [ scaledVol _ scaledVol + scaledVolIncr. ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or: [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]]) ifTrue: [ "reached the limit; stop incrementing" scaledVol _ scaledVolLimit. scaledVolIncr _ 0]]]. scaledIndex _ scaledNextIndex. count _ count - n. ! ! !ReverbSound methodsFor: 'private' stamp: 'ar 2/3/2001 15:55'! applyReverbTo: aSoundBuffer startingAt: startIndex count: n | delayedLeft delayedRight i tapGain j out | self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'. self var: #tapDelays declareC: 'int *tapDelays'. self var: #tapGains declareC: 'int *tapGains'. self var: #leftBuffer declareC: 'short int *leftBuffer'. self var: #rightBuffer declareC: 'short int *rightBuffer'. startIndex to: ((startIndex + n) - 1) do: [:sliceIndex | delayedLeft _ delayedRight _ 0. 1 to: tapCount do: [:tapIndex | i _ bufferIndex - (tapDelays at: tapIndex). i < 1 ifTrue: [i _ i + bufferSize]. "wrap" tapGain _ tapGains at: tapIndex. delayedLeft _ delayedLeft + (tapGain * (leftBuffer at: i)). delayedRight _ delayedRight + (tapGain * (rightBuffer at: i))]. "left channel" j _ (2 * sliceIndex) - 1. out _ (aSoundBuffer at: j) + (delayedLeft // ScaleFactor). out > 32767 ifTrue: [out _ 32767]. "clipping!!" out < -32767 ifTrue: [out _ -32767]. "clipping!!" aSoundBuffer at: j put: out. leftBuffer at: bufferIndex put: out. "right channel" j _ j + 1. out _ (aSoundBuffer at: j) + (delayedRight // ScaleFactor). out > 32767 ifTrue: [out _ 32767]. "clipping!!" out < -32767 ifTrue: [out _ -32767]. "clipping!!" aSoundBuffer at: j put: out. rightBuffer at: bufferIndex put: out. bufferIndex _ (bufferIndex \\ bufferSize) + 1]. ! ! !SampledSound methodsFor: 'playing' stamp: 'ar 2/3/2001 15:23'! mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol "Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1." | lastIndex outIndex sampleIndex sample i s overflow | self var: #aSoundBuffer declareC: 'short int *aSoundBuffer'. self var: #samples declareC: 'short int *samples'. lastIndex _ (startIndex + n) - 1. outIndex _ startIndex. "index of next stereo output sample pair" sampleIndex _ indexHighBits + (scaledIndex >> IncrementFractionBits). [(sampleIndex <= samplesSize) and: [outIndex <= lastIndex]] whileTrue: [ sample _ ((samples at: sampleIndex) * scaledVol) // ScaleFactor. leftVol > 0 ifTrue: [ i _ (2 * outIndex) - 1. s _ (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. rightVol > 0 ifTrue: [ i _ 2 * outIndex. s _ (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor). s > 32767 ifTrue: [s _ 32767]. "clipping!!" s < -32767 ifTrue: [s _ -32767]. "clipping!!" aSoundBuffer at: i put: s]. scaledVolIncr ~= 0 ifTrue: [ scaledVol _ scaledVol + scaledVolIncr. ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or: [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]]) ifTrue: [ "reached the limit; stop incrementing" scaledVol _ scaledVolLimit. scaledVolIncr _ 0]]. scaledIndex _ scaledIndex + scaledIncrement. scaledIndex >= ScaledIndexOverflow ifTrue: [ overflow _ scaledIndex >> IncrementFractionBits. indexHighBits _ indexHighBits + overflow. scaledIndex _ scaledIndex - (overflow << IncrementFractionBits)]. sampleIndex _ indexHighBits + (scaledIndex >> IncrementFractionBits). outIndex _ outIndex + 1]. count _ count - n. ! ! !SampledSound class methodsFor: 'utilities' stamp: 'ar 2/3/2001 16:14'! convert8bitSignedFrom: aByteArray to16Bit: aSoundBuffer "Copy the contents of the given array of signed 8-bit samples into the given array of 16-bit signed samples." | n s | self var: #aByteArray declareC: 'unsigned char *aByteArray'. self var: #aSoundBuffer declareC: 'unsigned short *aSoundBuffer'. n _ aByteArray size. 1 to: n do: [:i | s _ aByteArray at: i. s > 127 ifTrue: [aSoundBuffer at: i put: ((s - 256) bitShift: 8)] ifFalse: [aSoundBuffer at: i put: (s bitShift: 8)]]. ! ! !SoundCodecPlugin class methodsFor: 'accessing' stamp: 'ar 2/3/2001 16:28'! sourceFile ^ '/* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* This file was created by concatenating a number of separate header and source files from Jutta Degener and Carsten Bormann implementation, patch level 10. This was done to simplify Squeak source code maintenance. */ #include #include #include /****** begin "gsm.h" *****/ #ifdef __cplusplus # define NeedFunctionPrototypes 1 #endif #if __STDC__ # define NeedFunctionPrototypes 1 #endif #ifdef _NO_PROTO # undef NeedFunctionPrototypes #endif #ifdef NeedFunctionPrototypes # include /* for FILE * */ #endif #undef GSM_P #if NeedFunctionPrototypes # define GSM_P( protos ) protos #else # define GSM_P( protos ) ( /* protos */ ) #endif /* * Interface */ typedef struct gsm_state * gsm; typedef short gsm_signal; /* signed 16 bit */ typedef unsigned char gsm_byte; typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ #define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ #define GSM_PATCHLEVEL 10 #define GSM_MINOR 0 #define GSM_MAJOR 1 #define GSM_OPT_VERBOSE 1 #define GSM_OPT_FAST 2 #define GSM_OPT_LTP_CUT 3 #define GSM_OPT_WAV49 4 #define GSM_OPT_FRAME_INDEX 5 #define GSM_OPT_FRAME_CHAIN 6 extern gsm gsm_create GSM_P((void)); extern void gsm_destroy GSM_P((gsm)); extern int gsm_print GSM_P((FILE *, gsm, gsm_byte *)); extern int gsm_option GSM_P((gsm, int, int *)); extern void gsm_encode GSM_P((gsm, gsm_signal *, gsm_byte *)); extern int gsm_decode GSM_P((gsm, gsm_byte *, gsm_signal *)); extern int gsm_explode GSM_P((gsm, gsm_byte *, gsm_signal *)); extern void gsm_implode GSM_P((gsm, gsm_signal *, gsm_byte *)); /****** begin "proto.h" *****/ #if __cplusplus # define NeedFunctionPrototypes 1 #endif #if __STDC__ # define NeedFunctionPrototypes 1 #endif #ifdef _NO_PROTO # undef NeedFunctionPrototypes #endif #undef P /* gnu stdio.h actually defines this... */ #undef P0 #undef P1 #undef P2 #undef P3 #undef P4 #undef P5 #undef P6 #undef P7 #undef P8 #if NeedFunctionPrototypes # define P( protos ) protos # define P0() (void) # define P1(x, a) (a) # define P2(x, a, b) (a, b) # define P3(x, a, b, c) (a, b, c) # define P4(x, a, b, c, d) (a, b, c, d) # define P5(x, a, b, c, d, e) (a, b, c, d, e) # define P6(x, a, b, c, d, e, f) (a, b, c, d, e, f) # define P7(x, a, b, c, d, e, f, g) (a, b, c, d, e, f, g) # define P8(x, a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h) #else /* !!NeedFunctionPrototypes */ # define P( protos ) ( /* protos */ ) # define P0() () # define P1(x, a) x a; # define P2(x, a, b) x a; b; # define P3(x, a, b, c) x a; b; c; # define P4(x, a, b, c, d) x a; b; c; d; # define P5(x, a, b, c, d, e) x a; b; c; d; e; # define P6(x, a, b, c, d, e, f) x a; b; c; d; e; f; # define P7(x, a, b, c, d, e, f, g) x a; b; c; d; e; f; g; # define P8(x, a, b, c, d, e, f, g, h) x a; b; c; d; e; f; g; h; #endif /* !!NeedFunctionPrototypes */ /****** begin "private.h" *****/ typedef short word; /* 16 bit signed int */ typedef long longword; /* 32 bit signed int */ typedef unsigned short uword; /* unsigned word */ typedef unsigned long ulongword; /* unsigned longword */ struct gsm_state { word dp0[ 280 ]; word z1; /* preprocessing.c, Offset_com. */ longword L_z2; /* Offset_com. */ int mp; /* Preemphasis */ word u[8]; /* short_term_aly_filter.c */ word LARpp[2][8]; /* */ word j; /* */ word ltp_cut; /* long_term.c, LTP crosscorr. */ word nrp; /* 40 */ /* long_term.c, synthesis */ word v[9]; /* short_term.c, synthesis */ word msr; /* decoder.c, Postprocessing */ char verbose; /* only used if !!NDEBUG */ char fast; /* only used if FAST */ char wav_fmt; /* only used if WAV49 defined */ unsigned char frame_index; /* odd/even chaining */ unsigned char frame_chain; /* half-byte to carry forward */ }; #define MIN_WORD (-32767 - 1) #define MAX_WORD 32767 #define MIN_LONGWORD (-2147483647 - 1) #define MAX_LONGWORD 2147483647 #ifdef SASR /* flag: >> is a signed arithmetic shift right */ #undef SASR #define SASR(x, by) ((x) >> (by)) #else #define SASR(x, by) ((x) >= 0 ? (x) >> (by) : (~(-((x) + 1) >> (by)))) #endif /* SASR */ //#include "proto.h" /* * Prototypes from add.c */ extern word gsm_mult P((word a, word b)); extern longword gsm_L_mult P((word a, word b)); extern word gsm_mult_r P((word a, word b)); extern word gsm_div P((word num, word denum)); extern word gsm_add P(( word a, word b )); extern longword gsm_L_add P(( longword a, longword b )); extern word gsm_sub P((word a, word b)); extern longword gsm_L_sub P((longword a, longword b)); extern word gsm_abs P((word a)); extern word gsm_norm P(( longword a )); extern longword gsm_L_asl P((longword a, int n)); extern word gsm_asl P((word a, int n)); extern longword gsm_L_asr P((longword a, int n)); extern word gsm_asr P((word a, int n)); /* * Inlined functions from add.h */ /* * #define GSM_MULT_R(a, b) (* word a, word b, !!(a == b == MIN_WORD) *) \ * (0x0FFFF & SASR(((longword)(a) * (longword)(b) + 16384), 15)) */ #define GSM_MULT_R(a, b) /* word a, word b, !!(a == b == MIN_WORD) */ \ (SASR( ((longword)(a) * (longword)(b) + 16384), 15 )) # define GSM_MULT(a,b) /* word a, word b, !!(a == b == MIN_WORD) */ \ (SASR( ((longword)(a) * (longword)(b)), 15 )) # define GSM_L_MULT(a, b) /* word a, word b */ \ (((longword)(a) * (longword)(b)) << 1) # define GSM_L_ADD(a, b) \ ( (a) < 0 ? ( (b) >= 0 ? (a) + (b) \ : (utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1)) \ >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)utmp-2 ) \ : ((b) <= 0 ? (a) + (b) \ : (utmp = (ulongword)(a) + (ulongword)(b)) >= MAX_LONGWORD \ ? MAX_LONGWORD : utmp)) /* * # define GSM_ADD(a, b) \ * ((ltmp = (longword)(a) + (longword)(b)) >= MAX_WORD \ * ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) */ /* Nonportable, but faster: */ #define GSM_ADD(a, b) \ ((ulongword)((ltmp = (longword)(a) + (longword)(b)) - MIN_WORD) > \ MAX_WORD - MIN_WORD ? (ltmp > 0 ? MAX_WORD : MIN_WORD) : ltmp) # define GSM_SUB(a, b) \ ((ltmp = (longword)(a) - (longword)(b)) >= MAX_WORD \ ? MAX_WORD : ltmp <= MIN_WORD ? MIN_WORD : ltmp) # define GSM_ABS(a) ((a) < 0 ? ((a) == MIN_WORD ? MAX_WORD : -(a)) : (a)) /* Use these if necessary: # define GSM_MULT_R(a, b) gsm_mult_r(a, b) # define GSM_MULT(a, b) gsm_mult(a, b) # define GSM_L_MULT(a, b) gsm_L_mult(a, b) # define GSM_L_ADD(a, b) gsm_L_add(a, b) # define GSM_ADD(a, b) gsm_add(a, b) # define GSM_SUB(a, b) gsm_sub(a, b) # define GSM_ABS(a) gsm_abs(a) */ /* * More prototypes from implementations.. */ extern void Gsm_Coder P(( struct gsm_state * S, word * s, /* [0..159] samples IN */ word * LARc, /* [0..7] LAR coefficients OUT */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc /* [13*4] normalized RPE samples OUT */)); extern void Gsm_Long_Term_Predictor P(( /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d'' IN */ word * e, /* [0..40] OUT */ word * dpp, /* [0..40] OUT */ word * Nc, /* correlation lag OUT */ word * bc /* gain factor OUT */)); extern void Gsm_LPC_Analysis P(( struct gsm_state * S, word * s, /* 0..159 signals IN/OUT */ word * LARc)); /* 0..7 LARc''s OUT */ extern void Gsm_Preprocess P(( struct gsm_state * S, word * s, word * so)); extern void Gsm_Encoding P(( struct gsm_state * S, word * e, word * ep, word * xmaxc, word * Mc, word * xMc)); extern void Gsm_Short_Term_Analysis_Filter P(( struct gsm_state * S, word * LARc, /* coded log area ratio [0..7] IN */ word * d /* st res. signal [0..159] IN/OUT */)); extern void Gsm_Decoder P(( struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s)); /* [0..159] OUT */ extern void Gsm_Decoding P(( struct gsm_state * S, word xmaxcr, word Mcr, word * xMcr, /* [0..12] IN */ word * erp)); /* [0..39] OUT */ extern void Gsm_Long_Term_Synthesis_Filtering P(( struct gsm_state* S, word Ncr, word bcr, word * erp, /* [0..39] IN */ word * drp)); /* [-120..-1] IN, [0..40] OUT */ void Gsm_RPE_Decoding P(( struct gsm_state *S, word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */ word * erp)); /* [0..39] OUT */ void Gsm_RPE_Encoding P(( struct gsm_state * S, word * e, /* -5..-1][0..39][40..44 IN/OUT */ word * xmaxc, /* OUT */ word * Mc, /* OUT */ word * xMc)); /* [0..12] OUT */ extern void Gsm_Short_Term_Synthesis_Filter P(( struct gsm_state * S, word * LARcr, /* log area ratios [0..7] IN */ word * drp, /* received d [0...39] IN */ word * s)); /* signal s [0..159] OUT */ extern void Gsm_Update_of_reconstructed_short_time_residual_signal P(( word * dpp, /* [0...39] IN */ word * ep, /* [0...39] IN */ word * dp)); /* [-120...-1] IN/OUT */ /* * Tables from table.c */ #ifndef GSM_TABLE_C extern word gsm_A[8], gsm_B[8], gsm_MIC[8], gsm_MAC[8]; extern word gsm_INVA[8]; extern word gsm_DLB[4], gsm_QLB[4]; extern word gsm_H[11]; extern word gsm_NRFAC[8]; extern word gsm_FAC[8]; #endif /* GSM_TABLE_C */ /* * Debugging */ #ifdef NDEBUG # define gsm_debug_words(a, b, c, d) /* nil */ # define gsm_debug_longwords(a, b, c, d) /* nil */ # define gsm_debug_word(a, b) /* nil */ # define gsm_debug_longword(a, b) /* nil */ #else /* !!NDEBUG => DEBUG */ extern void gsm_debug_words P((char * name, int, int, word *)); extern void gsm_debug_longwords P((char * name, int, int, longword *)); extern void gsm_debug_longword P((char * name, longword)); extern void gsm_debug_word P((char * name, word)); #endif /* !!NDEBUG */ /****** begin "add.c" *****/ #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) word gsm_add P2((a,b), word a, word b) { longword sum = (longword)a + (longword)b; return saturate(sum); } word gsm_sub P2((a,b), word a, word b) { longword diff = (longword)a - (longword)b; return saturate(diff); } word gsm_mult P2((a,b), word a, word b) { if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; else return SASR( (longword)a * (longword)b, 15 ); } word gsm_mult_r P2((a,b), word a, word b) { if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; else { longword prod = (longword)a * (longword)b + 16384; prod >>= 15; return prod & 0xFFFF; } } word gsm_abs P1((a), word a) { return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; } longword gsm_L_mult P2((a,b),word a, word b) { assert( a !!= MIN_WORD || b !!= MIN_WORD ); return ((longword)a * (longword)b) << 1; } longword gsm_L_add P2((a,b), longword a, longword b) { if (a < 0) { if (b >= 0) return a + b; else { ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; } } else if (b <= 0) return a + b; else { ulongword A = (ulongword)a + (ulongword)b; return A > MAX_LONGWORD ? MAX_LONGWORD : A; } } longword gsm_L_sub P2((a,b), longword a, longword b) { if (a >= 0) { if (b >= 0) return a - b; else { /* a>=0, b<0 */ ulongword A = (ulongword)a + -(b + 1); return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); } } else if (b <= 0) return a - b; else { /* a<0, b>0 */ ulongword A = (ulongword)-(a + 1) + b; return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; } } static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; word gsm_norm P1((a), longword a ) /* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 ( -1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); * * (That''s ''ffs'', only from the left, not the right..) */ { assert(a !!= 0); if (a < 0) { if (a <= -1073741824) return 0; a = ~a; } return a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] ); } longword gsm_L_asl P2((a,n), longword a, int n) { if (n >= 32) return 0; if (n <= -32) return -(a < 0); if (n < 0) return gsm_L_asr(a, -n); return a << n; } word gsm_asl P2((a,n), word a, int n) { if (n >= 16) return 0; if (n <= -16) return -(a < 0); if (n < 0) return gsm_asr(a, -n); return a << n; } longword gsm_L_asr P2((a,n), longword a, int n) { if (n >= 32) return -(a < 0); if (n <= -32) return 0; if (n < 0) return a << -n; # ifdef SASR return a >> n; # else if (a >= 0) return a >> n; else return -(longword)( -(ulongword)a >> n ); # endif } word gsm_asr P2((a,n), word a, int n) { if (n >= 16) return -(a < 0); if (n <= -16) return 0; if (n < 0) return a << -n; # ifdef SASR return a >> n; # else if (a >= 0) return a >> n; else return -(word)( -(uword)a >> n ); # endif } /* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div(num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ word gsm_div P2((num,denum), word num, word denum) { longword L_num = num; longword L_denum = denum; word div = 0; int k = 15; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert(num !!= 0); */ assert(num >= 0 && denum >= num); if (num == 0) return 0; while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_denum) { L_num -= L_denum; div++; } } return div; } /****** begin "code.c" *****/ /* * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER */ void Gsm_Coder P8((S,s,LARc,Nc,bc,Mc,xmaxc,xMc), struct gsm_state * S, word * s, /* [0..159] samples IN */ /* * The RPE-LTD coder works on a frame by frame basis. The length of * the frame is equal to 160 samples. Some computations are done * once per frame to produce at the output of the coder the * LARc[1..8] parameters which are the coded LAR coefficients and * also to realize the inverse filtering operation for the entire * frame (160 samples of signal d[0..159]). These parts produce at * the output of the coder: */ word * LARc, /* [0..7] LAR coefficients OUT */ /* * Procedure 4.2.11 to 4.2.18 are to be executed four times per * frame. That means once for each sub-segment RPE-LTP analysis of * 40 samples. These parts produce at the output of the coder: */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc /* [13*4] normalized RPE samples OUT */ ) { int k; word * dp = S->dp0 + 120; /* [ -120...-1 ] */ word * dpp = dp; /* [ 0...39 ] */ static word e[50]; word so[160]; Gsm_Preprocess (S, s, so); Gsm_LPC_Analysis (S, so, LARc); Gsm_Short_Term_Analysis_Filter (S, LARc, so); for (k = 0; k <= 3; k++, xMc += 13) { Gsm_Long_Term_Predictor ( S, so+k*40, /* d [0..39] IN */ dp, /* dp [-120..-1] IN */ e + 5, /* e [0..39] OUT */ dpp, /* dpp [0..39] OUT */ Nc++, bc++); Gsm_RPE_Encoding ( S, e + 5, /* e ][0..39][ IN/OUT */ xmaxc++, Mc++, xMc ); /* * Gsm_Update_of_reconstructed_short_time_residual_signal * ( dpp, e + 5, dp ); */ { register int i; register longword ltmp; for (i = 0; i <= 39; i++) dp[ i ] = GSM_ADD( e[5 + i], dpp[i] ); } dp += 40; dpp += 40; } (void)memcpy( (char *)S->dp0, (char *)(S->dp0 + 160), 120 * sizeof(*S->dp0) ); } /****** begin "decode.c" *****/ /* * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER */ static void Postprocessing P2((S,s), struct gsm_state * S, register word * s) { register int k; register word msr = S->msr; register longword ltmp; /* for GSM_ADD */ register word tmp; for (k = 160; k--; s++) { tmp = GSM_MULT_R( msr, 28180 ); msr = GSM_ADD(*s, tmp); /* Deemphasis */ *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ } S->msr = msr; } void Gsm_Decoder P8((S,LARcr, Ncr,bcr,Mcr,xmaxcr,xMcr,s), struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s) /* [0..159] OUT */ { int j, k; word erp[40], wt[160]; word * drp = S->dp0 + 120; for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { Gsm_RPE_Decoding( S, *xmaxcr, *Mcr, xMcr, erp ); Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; } Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); Postprocessing(S, s); } /****** begin "gsm_decode.c" *****/ int gsm_decode P3((s, c, target), gsm s, gsm_byte * c, gsm_signal * target) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; #ifdef WAV49 if (s->wav_fmt) { uword sr = 0; s->frame_index = !!s->frame_index; if (s->frame_index) { sr = *c++; LARc[0] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 2; LARc[1] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 4; LARc[2] = sr & 0x1f; sr >>= 5; LARc[3] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 2; LARc[4] = sr & 0xf; sr >>= 4; LARc[5] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; /* 5 */ LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[0] = sr & 0x7f; sr >>= 7; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; sr = *c++; xmc[1] = sr & 0x7; sr >>= 3; xmc[2] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; xmc[5] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 10 */ xmc[6] = sr & 0x7; sr >>= 3; xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; sr = *c++; xmc[9] = sr & 0x7; sr >>= 3; xmc[10] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[1] = sr & 0x7f; sr >>= 7; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; sr = *c++; /* 15 */ xmc[14] = sr & 0x7; sr >>= 3; xmc[15] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; xmc[18] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[19] = sr & 0x7; sr >>= 3; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; sr = *c++; xmc[22] = sr & 0x7; sr >>= 3; xmc[23] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; /* 20 */ Nc[2] = sr & 0x7f; sr >>= 7; bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; sr = *c++; xmc[27] = sr & 0x7; sr >>= 3; xmc[28] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; xmc[31] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[32] = sr & 0x7; sr >>= 3; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; sr = *c++; /* 25 */ xmc[35] = sr & 0x7; sr >>= 3; xmc[36] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[3] = sr & 0x7f; sr >>= 7; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; sr = *c++; xmc[40] = sr & 0x7; sr >>= 3; xmc[41] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 30 */ xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; xmc[44] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[45] = sr & 0x7; sr >>= 3; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; sr = *c++; xmc[48] = sr & 0x7; sr >>= 3; xmc[49] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; s->frame_chain = sr & 0xf; } else { sr = s->frame_chain; sr |= (uword)*c++ << 4; /* 1 */ LARc[0] = sr & 0x3f; sr >>= 6; LARc[1] = sr & 0x3f; sr >>= 6; sr = *c++; LARc[2] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 3; LARc[3] = sr & 0x1f; sr >>= 5; LARc[4] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; LARc[5] = sr & 0xf; sr >>= 4; LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr = *c++; /* 5 */ Nc[0] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; xmc[1] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[2] = sr & 0x7; sr >>= 3; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; sr = *c++; xmc[5] = sr & 0x7; sr >>= 3; xmc[6] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 10 */ xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; xmc[9] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[10] = sr & 0x7; sr >>= 3; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr = *c++; Nc[1] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; xmc[14] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 15 */ xmc[15] = sr & 0x7; sr >>= 3; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; sr = *c++; xmc[18] = sr & 0x7; sr >>= 3; xmc[19] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; xmc[22] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[23] = sr & 0x7; sr >>= 3; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr = *c++; Nc[2] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; /* 20 */ bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; xmc[27] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[28] = sr & 0x7; sr >>= 3; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; sr = *c++; xmc[31] = sr & 0x7; sr >>= 3; xmc[32] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; xmc[35] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 25 */ xmc[36] = sr & 0x7; sr >>= 3; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr = *c++; Nc[3] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; xmc[40] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[41] = sr & 0x7; sr >>= 3; xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; sr = *c++; /* 30 */ xmc[44] = sr & 0x7; sr >>= 3; xmc[45] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; xmc[48] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[49] = sr & 0x7; sr >>= 3; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; } } else #endif { /* GSM_MAGIC = (*c >> 4) & 0xF; */ if (((*c >> 4) & 0x0F) !!= GSM_MAGIC) return -1; LARc[0] = (*c++ & 0xF) << 2; /* 1 */ LARc[0] |= (*c >> 6) & 0x3; LARc[1] = *c++ & 0x3F; LARc[2] = (*c >> 3) & 0x1F; LARc[3] = (*c++ & 0x7) << 2; LARc[3] |= (*c >> 6) & 0x3; LARc[4] = (*c >> 2) & 0xF; LARc[5] = (*c++ & 0x3) << 2; LARc[5] |= (*c >> 6) & 0x3; LARc[6] = (*c >> 3) & 0x7; LARc[7] = *c++ & 0x7; Nc[0] = (*c >> 1) & 0x7F; bc[0] = (*c++ & 0x1) << 1; bc[0] |= (*c >> 7) & 0x1; Mc[0] = (*c >> 5) & 0x3; xmaxc[0] = (*c++ & 0x1F) << 1; xmaxc[0] |= (*c >> 7) & 0x1; xmc[0] = (*c >> 4) & 0x7; xmc[1] = (*c >> 1) & 0x7; xmc[2] = (*c++ & 0x1) << 2; xmc[2] |= (*c >> 6) & 0x3; xmc[3] = (*c >> 3) & 0x7; xmc[4] = *c++ & 0x7; xmc[5] = (*c >> 5) & 0x7; xmc[6] = (*c >> 2) & 0x7; xmc[7] = (*c++ & 0x3) << 1; /* 10 */ xmc[7] |= (*c >> 7) & 0x1; xmc[8] = (*c >> 4) & 0x7; xmc[9] = (*c >> 1) & 0x7; xmc[10] = (*c++ & 0x1) << 2; xmc[10] |= (*c >> 6) & 0x3; xmc[11] = (*c >> 3) & 0x7; xmc[12] = *c++ & 0x7; Nc[1] = (*c >> 1) & 0x7F; bc[1] = (*c++ & 0x1) << 1; bc[1] |= (*c >> 7) & 0x1; Mc[1] = (*c >> 5) & 0x3; xmaxc[1] = (*c++ & 0x1F) << 1; xmaxc[1] |= (*c >> 7) & 0x1; xmc[13] = (*c >> 4) & 0x7; xmc[14] = (*c >> 1) & 0x7; xmc[15] = (*c++ & 0x1) << 2; xmc[15] |= (*c >> 6) & 0x3; xmc[16] = (*c >> 3) & 0x7; xmc[17] = *c++ & 0x7; xmc[18] = (*c >> 5) & 0x7; xmc[19] = (*c >> 2) & 0x7; xmc[20] = (*c++ & 0x3) << 1; xmc[20] |= (*c >> 7) & 0x1; xmc[21] = (*c >> 4) & 0x7; xmc[22] = (*c >> 1) & 0x7; xmc[23] = (*c++ & 0x1) << 2; xmc[23] |= (*c >> 6) & 0x3; xmc[24] = (*c >> 3) & 0x7; xmc[25] = *c++ & 0x7; Nc[2] = (*c >> 1) & 0x7F; bc[2] = (*c++ & 0x1) << 1; /* 20 */ bc[2] |= (*c >> 7) & 0x1; Mc[2] = (*c >> 5) & 0x3; xmaxc[2] = (*c++ & 0x1F) << 1; xmaxc[2] |= (*c >> 7) & 0x1; xmc[26] = (*c >> 4) & 0x7; xmc[27] = (*c >> 1) & 0x7; xmc[28] = (*c++ & 0x1) << 2; xmc[28] |= (*c >> 6) & 0x3; xmc[29] = (*c >> 3) & 0x7; xmc[30] = *c++ & 0x7; xmc[31] = (*c >> 5) & 0x7; xmc[32] = (*c >> 2) & 0x7; xmc[33] = (*c++ & 0x3) << 1; xmc[33] |= (*c >> 7) & 0x1; xmc[34] = (*c >> 4) & 0x7; xmc[35] = (*c >> 1) & 0x7; xmc[36] = (*c++ & 0x1) << 2; xmc[36] |= (*c >> 6) & 0x3; xmc[37] = (*c >> 3) & 0x7; xmc[38] = *c++ & 0x7; Nc[3] = (*c >> 1) & 0x7F; bc[3] = (*c++ & 0x1) << 1; bc[3] |= (*c >> 7) & 0x1; Mc[3] = (*c >> 5) & 0x3; xmaxc[3] = (*c++ & 0x1F) << 1; xmaxc[3] |= (*c >> 7) & 0x1; xmc[39] = (*c >> 4) & 0x7; xmc[40] = (*c >> 1) & 0x7; xmc[41] = (*c++ & 0x1) << 2; xmc[41] |= (*c >> 6) & 0x3; xmc[42] = (*c >> 3) & 0x7; xmc[43] = *c++ & 0x7; /* 30 */ xmc[44] = (*c >> 5) & 0x7; xmc[45] = (*c >> 2) & 0x7; xmc[46] = (*c++ & 0x3) << 1; xmc[46] |= (*c >> 7) & 0x1; xmc[47] = (*c >> 4) & 0x7; xmc[48] = (*c >> 1) & 0x7; xmc[49] = (*c++ & 0x1) << 2; xmc[49] |= (*c >> 6) & 0x3; xmc[50] = (*c >> 3) & 0x7; xmc[51] = *c & 0x7; /* 33 */ } Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); return 0; } /****** begin "gsm_encode.c" *****/ void gsm_encode P3((s, source, c), gsm s, gsm_signal * source, gsm_byte * c) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); /* variable size GSM_MAGIC 4 LARc[0] 6 LARc[1] 6 LARc[2] 5 LARc[3] 5 LARc[4] 4 LARc[5] 4 LARc[6] 3 LARc[7] 3 Nc[0] 7 bc[0] 2 Mc[0] 2 xmaxc[0] 6 xmc[0] 3 xmc[1] 3 xmc[2] 3 xmc[3] 3 xmc[4] 3 xmc[5] 3 xmc[6] 3 xmc[7] 3 xmc[8] 3 xmc[9] 3 xmc[10] 3 xmc[11] 3 xmc[12] 3 Nc[1] 7 bc[1] 2 Mc[1] 2 xmaxc[1] 6 xmc[13] 3 xmc[14] 3 xmc[15] 3 xmc[16] 3 xmc[17] 3 xmc[18] 3 xmc[19] 3 xmc[20] 3 xmc[21] 3 xmc[22] 3 xmc[23] 3 xmc[24] 3 xmc[25] 3 Nc[2] 7 bc[2] 2 Mc[2] 2 xmaxc[2] 6 xmc[26] 3 xmc[27] 3 xmc[28] 3 xmc[29] 3 xmc[30] 3 xmc[31] 3 xmc[32] 3 xmc[33] 3 xmc[34] 3 xmc[35] 3 xmc[36] 3 xmc[37] 3 xmc[38] 3 Nc[3] 7 bc[3] 2 Mc[3] 2 xmaxc[3] 6 xmc[39] 3 xmc[40] 3 xmc[41] 3 xmc[42] 3 xmc[43] 3 xmc[44] 3 xmc[45] 3 xmc[46] 3 xmc[47] 3 xmc[48] 3 xmc[49] 3 xmc[50] 3 xmc[51] 3 */ #ifdef WAV49 if (s->wav_fmt) { s->frame_index = !!s->frame_index; if (s->frame_index) { uword sr; sr = 0; sr = sr >> 6 | LARc[0] << 10; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 4; sr = sr >> 5 | LARc[2] << 11; *c++ = sr >> 7; sr = sr >> 5 | LARc[3] << 11; sr = sr >> 4 | LARc[4] << 12; *c++ = sr >> 6; sr = sr >> 4 | LARc[5] << 12; sr = sr >> 3 | LARc[6] << 13; *c++ = sr >> 7; sr = sr >> 3 | LARc[7] << 13; sr = sr >> 7 | Nc[0] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[0] << 14; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[0] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; sr = sr >> 3 | xmc[3] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[4] << 13; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[7] << 13; sr = sr >> 3 | xmc[8] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; sr = sr >> 3 | xmc[11] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[12] << 13; sr = sr >> 7 | Nc[1] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[1] << 14; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[13] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; sr = sr >> 3 | xmc[16] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[17] << 13; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[20] << 13; sr = sr >> 3 | xmc[21] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; sr = sr >> 3 | xmc[24] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[25] << 13; sr = sr >> 7 | Nc[2] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[2] << 14; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[26] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; sr = sr >> 3 | xmc[29] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[30] << 13; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[33] << 13; sr = sr >> 3 | xmc[34] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; sr = sr >> 3 | xmc[37] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[38] << 13; sr = sr >> 7 | Nc[3] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[3] << 14; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[39] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; sr = sr >> 3 | xmc[42] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[43] << 13; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[46] << 13; sr = sr >> 3 | xmc[47] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; sr = sr >> 3 | xmc[50] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[51] << 13; sr = sr >> 4; *c = sr >> 8; s->frame_chain = *c; } else { uword sr; sr = 0; sr = sr >> 4 | s->frame_chain << 12; sr = sr >> 6 | LARc[0] << 10; *c++ = sr >> 6; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 8; sr = sr >> 5 | LARc[2] << 11; sr = sr >> 5 | LARc[3] << 11; *c++ = sr >> 6; sr = sr >> 4 | LARc[4] << 12; sr = sr >> 4 | LARc[5] << 12; *c++ = sr >> 6; sr = sr >> 3 | LARc[6] << 13; sr = sr >> 3 | LARc[7] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[0] << 9; sr = sr >> 2 | bc[0] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[0] << 13; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[3] << 13; sr = sr >> 3 | xmc[4] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; sr = sr >> 3 | xmc[7] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[8] << 13; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[11] << 13; sr = sr >> 3 | xmc[12] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[1] << 9; sr = sr >> 2 | bc[1] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[13] << 13; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[16] << 13; sr = sr >> 3 | xmc[17] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; sr = sr >> 3 | xmc[20] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[21] << 13; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[24] << 13; sr = sr >> 3 | xmc[25] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[2] << 9; sr = sr >> 2 | bc[2] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[26] << 13; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[29] << 13; sr = sr >> 3 | xmc[30] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; sr = sr >> 3 | xmc[33] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[34] << 13; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[37] << 13; sr = sr >> 3 | xmc[38] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[3] << 9; sr = sr >> 2 | bc[3] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[39] << 13; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[42] << 13; sr = sr >> 3 | xmc[43] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; sr = sr >> 3 | xmc[46] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[47] << 13; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[50] << 13; sr = sr >> 3 | xmc[51] << 13; *c++ = sr >> 8; } } else #endif /* WAV49 */ { *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ | ((LARc[0] >> 2) & 0xF); *c++ = ((LARc[0] & 0x3) << 6) | (LARc[1] & 0x3F); *c++ = ((LARc[2] & 0x1F) << 3) | ((LARc[3] >> 2) & 0x7); *c++ = ((LARc[3] & 0x3) << 6) | ((LARc[4] & 0xF) << 2) | ((LARc[5] >> 2) & 0x3); *c++ = ((LARc[5] & 0x3) << 6) | ((LARc[6] & 0x7) << 3) | (LARc[7] & 0x7); *c++ = ((Nc[0] & 0x7F) << 1) | ((bc[0] >> 1) & 0x1); *c++ = ((bc[0] & 0x1) << 7) | ((Mc[0] & 0x3) << 5) | ((xmaxc[0] >> 1) & 0x1F); *c++ = ((xmaxc[0] & 0x1) << 7) | ((xmc[0] & 0x7) << 4) | ((xmc[1] & 0x7) << 1) | ((xmc[2] >> 2) & 0x1); *c++ = ((xmc[2] & 0x3) << 6) | ((xmc[3] & 0x7) << 3) | (xmc[4] & 0x7); *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ | ((xmc[6] & 0x7) << 2) | ((xmc[7] >> 1) & 0x3); *c++ = ((xmc[7] & 0x1) << 7) | ((xmc[8] & 0x7) << 4) | ((xmc[9] & 0x7) << 1) | ((xmc[10] >> 2) & 0x1); *c++ = ((xmc[10] & 0x3) << 6) | ((xmc[11] & 0x7) << 3) | (xmc[12] & 0x7); *c++ = ((Nc[1] & 0x7F) << 1) | ((bc[1] >> 1) & 0x1); *c++ = ((bc[1] & 0x1) << 7) | ((Mc[1] & 0x3) << 5) | ((xmaxc[1] >> 1) & 0x1F); *c++ = ((xmaxc[1] & 0x1) << 7) | ((xmc[13] & 0x7) << 4) | ((xmc[14] & 0x7) << 1) | ((xmc[15] >> 2) & 0x1); *c++ = ((xmc[15] & 0x3) << 6) | ((xmc[16] & 0x7) << 3) | (xmc[17] & 0x7); *c++ = ((xmc[18] & 0x7) << 5) | ((xmc[19] & 0x7) << 2) | ((xmc[20] >> 1) & 0x3); *c++ = ((xmc[20] & 0x1) << 7) | ((xmc[21] & 0x7) << 4) | ((xmc[22] & 0x7) << 1) | ((xmc[23] >> 2) & 0x1); *c++ = ((xmc[23] & 0x3) << 6) | ((xmc[24] & 0x7) << 3) | (xmc[25] & 0x7); *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ | ((bc[2] >> 1) & 0x1); *c++ = ((bc[2] & 0x1) << 7) | ((Mc[2] & 0x3) << 5) | ((xmaxc[2] >> 1) & 0x1F); *c++ = ((xmaxc[2] & 0x1) << 7) | ((xmc[26] & 0x7) << 4) | ((xmc[27] & 0x7) << 1) | ((xmc[28] >> 2) & 0x1); *c++ = ((xmc[28] & 0x3) << 6) | ((xmc[29] & 0x7) << 3) | (xmc[30] & 0x7); *c++ = ((xmc[31] & 0x7) << 5) | ((xmc[32] & 0x7) << 2) | ((xmc[33] >> 1) & 0x3); *c++ = ((xmc[33] & 0x1) << 7) | ((xmc[34] & 0x7) << 4) | ((xmc[35] & 0x7) << 1) | ((xmc[36] >> 2) & 0x1); *c++ = ((xmc[36] & 0x3) << 6) | ((xmc[37] & 0x7) << 3) | (xmc[38] & 0x7); *c++ = ((Nc[3] & 0x7F) << 1) | ((bc[3] >> 1) & 0x1); *c++ = ((bc[3] & 0x1) << 7) | ((Mc[3] & 0x3) << 5) | ((xmaxc[3] >> 1) & 0x1F); *c++ = ((xmaxc[3] & 0x1) << 7) | ((xmc[39] & 0x7) << 4) | ((xmc[40] & 0x7) << 1) | ((xmc[41] >> 2) & 0x1); *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ | ((xmc[42] & 0x7) << 3) | (xmc[43] & 0x7); *c++ = ((xmc[44] & 0x7) << 5) | ((xmc[45] & 0x7) << 2) | ((xmc[46] >> 1) & 0x3); *c++ = ((xmc[46] & 0x1) << 7) | ((xmc[47] & 0x7) << 4) | ((xmc[48] & 0x7) << 1) | ((xmc[49] >> 2) & 0x1); *c++ = ((xmc[49] & 0x3) << 6) | ((xmc[50] & 0x7) << 3) | (xmc[51] & 0x7); } } /****** begin "long_term.c" *****/ /* * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION */ /* * This module computes the LTP gain (bc) and the LTP lag (Nc) * for the long term analysis filter. This is done by calculating a * maximum of the cross-correlation function between the current * sub-segment short term residual signal d[0..39] (output of * the short term analysis filter; for simplification the index * of this array begins at 0 and ends at 39 for each sub-segment of the * RPE-LTP analysis) and the previous reconstructed short term * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be * performed to avoid overflow. */ /* The next procedure exists in six versions. First two integer * version (if USE_FLOAT_MUL is not defined); then four floating * point versions, twice with proper scaling (USE_FLOAT_MUL defined), * once without (USE_FLOAT_MUL and FAST defined, and fast run-time * option used). Every pair has first a Cut version (see the -C * option to toast or the LTP_CUT option to gsm_option()), then the * uncut one. (For a detailed explanation of why this is altogether * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered * Harmful''''.) */ #ifndef USE_FLOAT_MUL #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_result; longword L_max, L_power; word R, S, dmax, scal, best_k; word ltp_cut; register word temp, wt_k; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) { dmax = temp; best_k = k; } } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ wt_k = SASR(d[best_k], scal); for (lambda = 40; lambda <= 120; lambda++) { L_result = (longword)wt_k * dp[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k <= 39; k++) wt[k] = SASR( d[k], scal ); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { # undef STEP # define STEP(k) (longword)wt[k] * dp[k - lambda] register longword L_result; L_result = STEP(0) ; L_result += STEP(1) ; L_result += STEP(2) ; L_result += STEP(3) ; L_result += STEP(4) ; L_result += STEP(5) ; L_result += STEP(6) ; L_result += STEP(7) ; L_result += STEP(8) ; L_result += STEP(9) ; L_result += STEP(10) ; L_result += STEP(11) ; L_result += STEP(12) ; L_result += STEP(13) ; L_result += STEP(14) ; L_result += STEP(15) ; L_result += STEP(16) ; L_result += STEP(17) ; L_result += STEP(18) ; L_result += STEP(19) ; L_result += STEP(20) ; L_result += STEP(21) ; L_result += STEP(22) ; L_result += STEP(23) ; L_result += STEP(24) ; L_result += STEP(25) ; L_result += STEP(26) ; L_result += STEP(27) ; L_result += STEP(28) ; L_result += STEP(29) ; L_result += STEP(30) ; L_result += STEP(31) ; L_result += STEP(32) ; L_result += STEP(33) ; L_result += STEP(34) ; L_result += STEP(35) ; L_result += STEP(36) ; L_result += STEP(37) ; L_result += STEP(38) ; L_result += STEP(39) ; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #else /* USE_FLOAT_MUL */ #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word ltp_cut; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); ltp_cut = (longword)SASR(dmax, scal) * st->ltp_cut / 100; /* Initialization of a working array wt */ for (k = 0; k < 40; k++) { register word w = SASR( d[k], scal ); if (w < 0 ? w > -ltp_cut : w < ltp_cut) { wt_float[k] = 0.0; } else { wt_float[k] = w; } } for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ if ((W = wt_float[K]) !!= 0.0) { \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E; } else (a = lp[K]) # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k < 40; k++) wt_float[k] = SASR( d[k], scal ); for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #ifdef FAST #ifdef LTP_CUT static void Cut_Fast_Calculation_of_the_LTP_parameters P5((st, d,dp,bc_out,Nc_out), struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; register float wt_float; word Nc, bc; word wt_max, best_k, ltp_cut; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_result, L_max, L_power; wt_max = 0; for (k = 0; k < 40; ++k) { if ( d[k] > wt_max) wt_max = d[best_k = k]; else if (-d[k] > wt_max) wt_max = -d[best_k = k]; } assert(wt_max >= 0); wt_float = (float)wt_max; for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { L_result = wt_float * dp_float[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Fast_Calculation_of_the_LTP_parameters P4((d,dp,bc_out,Nc_out), register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_max, L_power; for (k = 0; k < 40; ++k) wt_float[k] = (float)d[k]; for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef STEP # define STEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h) # define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a) # define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b) # define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c) # define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d) # define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e) # define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f) # define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g) STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3); STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7); STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11); STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15); STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19); STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23); STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27); STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31); STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35); STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* FAST */ #endif /* USE_FLOAT_MUL */ /* 4.2.12 */ static void Long_term_analysis_filtering P6((bc,Nc,dp,d,dpp,e), word bc, /* IN */ word Nc, /* IN */ register word * dp, /* previous d [-120..-1] IN */ register word * d, /* d [0..39] IN */ register word * dpp, /* estimate [0..39] OUT */ register word * e /* long term res. signal [0..39] OUT */ ) /* * In this part, we have to decode the bc parameter to compute * the samples of the estimate dpp[0..39]. The decoding of bc needs the * use of table 4.3b. The long term residual signal e[0..39] * is then calculated to be fed to the RPE encoding section. */ { register int k; register longword ltmp; # undef STEP # define STEP(BP) \ for (k = 0; k <= 39; k++) { \ dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ e[k] = GSM_SUB( d[k], dpp[k] ); \ } switch (bc) { case 0: STEP( 3277 ); break; case 1: STEP( 11469 ); break; case 2: STEP( 21299 ); break; case 3: STEP( 32767 ); break; } } void Gsm_Long_Term_Predictor P7((S,d,dp,e,dpp,Nc,bc), /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d'' IN */ word * e, /* [0..39] OUT */ word * dpp, /* [0..39] OUT */ word * Nc, /* correlation lag OUT */ word * bc /* gain factor OUT */ ) { assert( d ); assert( dp ); assert( e ); assert( dpp); assert( Nc ); assert( bc ); #if defined(FAST) && defined(USE_FLOAT_MUL) if (S->fast) #if defined (LTP_CUT) if (S->ltp_cut) Cut_Fast_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif /* LTP_CUT */ Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); else #endif /* FAST & USE_FLOAT_MUL */ #ifdef LTP_CUT if (S->ltp_cut) Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif Calculation_of_the_LTP_parameters(d, dp, bc, Nc); Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); } /* 4.3.2 */ void Gsm_Long_Term_Synthesis_Filtering P5((S,Ncr,bcr,erp,drp), struct gsm_state * S, word Ncr, word bcr, register word * erp, /* [0..39] IN */ register word * drp /* [-120..-1] IN, [-120..40] OUT */ ) /* * This procedure uses the bcr and Ncr parameter to realize the * long term synthesis filtering. The decoding of bcr needs * table 4.3b. */ { register longword ltmp; /* for ADD */ register int k; word brp, drpp, Nr; /* Check the limits of Nr. */ Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; S->nrp = Nr; assert(Nr >= 40 && Nr <= 120); /* Decoding of the LTP gain bcr */ brp = gsm_QLB[ bcr ]; /* Computation of the reconstructed short term residual * signal drp[0..39] */ assert(brp !!= MIN_WORD); for (k = 0; k <= 39; k++) { drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); drp[k] = GSM_ADD( erp[k], drpp ); } /* * Update of the reconstructed short term residual signal * drp[ -1..-120 ] */ for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; } /****** begin "lpc.c" *****/ #undef STEP #undef P /* * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION */ /* 4.2.4 */ static void Autocorrelation P2((s, L_ACF), word * s, /* [0..159] IN/OUT */ longword * L_ACF) /* [0..8] OUT */ /* * The goal is to compute the array L_ACF[k]. The signal s[i] must * be scaled in order to avoid an overflow situation. */ { register int k, i; word temp, smax, scalauto; #ifdef USE_FLOAT_MUL float float_s[160]; #endif /* Dynamic scaling of the array s[0..159] */ /* Search for the maximum. */ smax = 0; for (k = 0; k <= 159; k++) { temp = GSM_ABS( s[k] ); if (temp > smax) smax = temp; } /* Computation of the scaling factor. */ if (smax == 0) scalauto = 0; else { assert(smax > 0); scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ } /* Scaling of the array s[0...159] */ if (scalauto > 0) { # ifdef USE_FLOAT_MUL # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ float_s[k] = (float) \ (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ break; # else # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ break; # endif /* USE_FLOAT_MUL */ switch (scalauto) { SCALE(1) SCALE(2) SCALE(3) SCALE(4) } # undef SCALE } # ifdef USE_FLOAT_MUL else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; # endif /* Compute the L_ACF[..]. */ { # ifdef USE_FLOAT_MUL register float * sp = float_s; register float sl = *sp; # define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); # else word * sp = s; word sl = *sp; # define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); # endif # define NEXTI sl = *+