Skip to content

Commit

Permalink
Add stereo bar and microphone clamps
Browse files Browse the repository at this point in the history
For #5
  • Loading branch information
svetter committed Aug 8, 2024
1 parent 153ac9a commit 7bac72d
Show file tree
Hide file tree
Showing 6 changed files with 1,168 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
private val micShadowImage: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.mic_shadow)
private val cableVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable)
private val cableShadowImage: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable_shadow)
private val stereoBarVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.stereo_bar)
private val micClampVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.mic_clamp)
private val micClampWheelVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.mic_clamp_wheel)


private val cmPerInch = 2.54f
Expand All @@ -65,25 +68,34 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
// Input graphics parameters
private val micWidthCm = 2f
private val micHeightCm = 8f
private val micCenterYOffsetCm = 1f
private val cableWidthCm = 11f
private val cableHeightCm = 16.5f
private val cableCenterXCm = 1f
private val stereoBarWidthCm = 53.4f
private val stereoBarHeightCm = 3.4f
private val micClampWithCm = 3f
private val micClampHeightCm = micHeightCm
private val micClampCenterXRelativeToMicTopCm = 6f
private val shadowOverhangCm = 1f
// Layout
private val shadowXOffsetCm = -0.5f
private val shadowYOffsetCm = 0.3f
private val maxShadowAlpha = 200
private val cableVisibleUntilDeg = 155
private val cableInvisibleFromDeg = 170
private val shadowXOffsetCm = -0.5f
private val shadowYOffsetCm = 0.3f
private val maxShadowAlpha = 200

private val halfCircleRadiusCm = maxMicDistanceCm / 2f

// Calculations
private var pixelPerCm = -1f
private var micWidth = -1f
private var micHeight = -1f
private var micCenterYOffset = -1f
private var cableWidth = -1f
private var cableHeight = -1f
private var stereoBarWidth = -1f
private var stereoBarHeight = -1f
private var micClampWidth = -1f
private var micClampHeight = -1f
private var shadowOverhang = -1f
private var shadowXOffset = -1f
private var shadowYOffset = -1f
Expand Down Expand Up @@ -201,41 +213,51 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
}

private fun drawMicView(canvas: Canvas) {
val picturedWidth = maxMicDistanceCm + micWidthCm * 1.5f // Max mic distance (center to center) + sqrt(2) for each mic when at max distance and 45°
val picturedWidth = maxMicDistanceCm + micWidthCm + 2 * shadowOverhangCm
val picturedHeight = halfCircleRadiusCm + micHeightCm - 1 + 1 // Circle radius + mic length - 1cm for the top of the mic + 1cm buffer
pixelPerCm = width / picturedWidth

micWidth = micWidthCm * pixelPerCm
micHeight = micHeightCm * pixelPerCm
cableWidth = cableWidthCm * pixelPerCm
cableHeight = cableHeightCm * pixelPerCm
shadowOverhang = shadowOverhangCm * pixelPerCm
shadowXOffset = shadowXOffsetCm * pixelPerCm
shadowYOffset = shadowYOffsetCm * pixelPerCm
val halfMicDistance = micDistance / 2f * pixelPerCm
micWidth = micWidthCm * pixelPerCm
micHeight = micHeightCm * pixelPerCm
micCenterYOffset = micCenterYOffsetCm * pixelPerCm
cableWidth = cableWidthCm * pixelPerCm
cableHeight = cableHeightCm * pixelPerCm
stereoBarWidth = stereoBarWidthCm * pixelPerCm
stereoBarHeight = stereoBarHeightCm * pixelPerCm
micClampWidth = micClampWithCm * pixelPerCm
micClampHeight = micClampHeightCm * pixelPerCm
shadowOverhang = shadowOverhangCm * pixelPerCm
shadowXOffset = shadowXOffsetCm * pixelPerCm
shadowYOffset = shadowYOffsetCm * pixelPerCm
val halfMicDistance = micDistance / 2f * pixelPerCm

centerX = width / 2f
centerY = height - micHeight
left = 0f
right = width.toFloat()
top = 0f

val leftMicCenterX = centerX - halfMicDistance
val leftMicLeftX = leftMicCenterX - micWidth / 2
val rightMicCenterX = centerX + halfMicDistance
val rightMicLeftX = rightMicCenterX - micWidth / 2
val cableCenterX = cableCenterXCm * pixelPerCm

val micTopY = centerY - 1 * pixelPerCm
val micBottomY = micTopY + micHeight
val cableTopY = micBottomY - 0.25f * pixelPerCm // Slight overlap to line up the shadows

val angleWithXAxisDeg = 90 - recAngle / 2
val angleWithXAxisRad = angleWithXAxisDeg * Math.PI.toFloat() / 180
val recAngleLineY = centerY - tan(angleWithXAxisRad) * centerX
val halfAngleWithXAxisDeg = 90 - recAngle * (0.25f + angularDist / 60f)
val halfAngleWithXAxisRad = halfAngleWithXAxisDeg * Math.PI.toFloat() / 180
val halfRecAngleLineY = centerY - tan(halfAngleWithXAxisRad) * centerX
val leftMicCenterX = centerX - halfMicDistance
val leftMicLeftX = leftMicCenterX - micWidth / 2
val rightMicCenterX = centerX + halfMicDistance
val rightMicLeftX = rightMicCenterX - micWidth / 2
val cableCenterX = cableCenterXCm * pixelPerCm
val leftClampLeftX = leftMicCenterX - micClampWidth / 2
val rightClampLeftX = rightMicCenterX - micClampWidth / 2
val stereoBarLeftX = centerX - stereoBarWidth / 2
val stereoBarCenterY = centerY + (micClampCenterXRelativeToMicTopCm * pixelPerCm - micCenterYOffset) * cos(Math.toRadians(micAngle / 2.0)).toFloat()
val stereoBarTopY = stereoBarCenterY - stereoBarHeight / 2

val micTopY = centerY - micCenterYOffset
val micBottomY = micTopY + micHeight
val cableTopY = micBottomY - 0.25f * pixelPerCm // Slight overlap to line up the shadows

val angleWithXAxisDeg = 90 - recAngle / 2
val angleWithXAxisRad = angleWithXAxisDeg * Math.PI.toFloat() / 180
val recAngleLineY = centerY - tan(angleWithXAxisRad) * centerX
val halfAngleWithXAxisDeg = 90 - recAngle * (0.25f + angularDist / 60f)
val halfAngleWithXAxisRad = halfAngleWithXAxisDeg * Math.PI.toFloat() / 180
val halfRecAngleLineY = centerY - tan(halfAngleWithXAxisRad) * centerX

val circleRadius = halfCircleRadiusCm * pixelPerCm

Expand Down Expand Up @@ -276,28 +298,36 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
)
}

// Draw shadows and microphones
micShadowImage?.alpha = maxShadowAlpha

// Vary mirrored microphone alpha based on angle to simulate light reflections
micVectorMirrored?.alpha = (128 * (1 - cos(Math.toRadians(micAngle / 2.0)))).roundToInt()
// Draw stereo bar
draw(canvas, stereoBarVector, stereoBarLeftX, stereoBarTopY, stereoBarWidth, stereoBarHeight)

val leftRotAngle = -micAngle / 2
val rightRotAngle = micAngle / 2
val leftCableCenterX = leftMicLeftX + cableCenterX
val rightCableCenterX = rightMicLeftX + cableCenterX

// drawable leftX topY width height rotationAngle rotationCenterX, rotationCenterY
// Draw clamp wheels
draw(canvas, micClampWheelVector, rightClampLeftX, micTopY, micClampWidth, micClampHeight, rightRotAngle, rightCableCenterX, centerY)
draw(canvas, micClampWheelVector, leftClampLeftX, micTopY, micClampWidth, micClampHeight, leftRotAngle, leftCableCenterX, centerY)

// Vary mirrored microphone alpha based on angle to simulate light reflections
micVectorMirrored?.alpha = (128 * (1 - cos(Math.toRadians(micAngle / 2.0)))).roundToInt()

// Draw shadows, microphones and clamps
micShadowImage?.alpha = maxShadowAlpha
// drawable leftX topY width height rotationAngle rotationCenterX, rotationCenterY
// RIGHT
drawShadow (canvas, cableShadowImage, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, rotationCenterY = centerY)
drawShadow (canvas, micShadowImage, rightMicLeftX, micTopY, micWidth, micHeight, rightRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, centerY)
drawMic (canvas, rightNotLeft = true, rightMicLeftX, micTopY)
drawShadow (canvas, cableShadowImage, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, rotationCenterY = centerY)
drawShadow (canvas, micShadowImage, rightMicLeftX, micTopY, micWidth, micHeight, rightRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, centerY)
drawMic (canvas, rightNotLeft = true, rightMicLeftX, micTopY)
draw (canvas, micClampVector, rightClampLeftX, micTopY, micClampWidth, micClampHeight, rightRotAngle, rightCableCenterX, centerY)
// LEFT
drawShadow (canvas, cableShadowImage, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawShadow (canvas, micShadowImage, leftMicLeftX, micTopY, micWidth, micHeight, leftRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawMic (canvas, rightNotLeft = false, leftMicLeftX, micTopY)
drawShadow (canvas, cableShadowImage, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawShadow (canvas, micShadowImage, leftMicLeftX, micTopY, micWidth, micHeight, leftRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawMic (canvas, rightNotLeft = false, leftMicLeftX, micTopY)
draw (canvas, micClampVector, leftClampLeftX, micTopY, micClampWidth, micClampHeight, leftRotAngle, leftCableCenterX, centerY)
}

private fun drawGraphView(canvas: Canvas) {
Expand Down
45 changes: 45 additions & 0 deletions app/src/main/res/drawable/mic_clamp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="30dp"
android:height="80dp"
android:viewportWidth="300"
android:viewportHeight="800">
<path
android:pathData="M225,500L255,500A5,5 0,0 1,260 505L260,695A5,5 0,0 1,255 700L225,700A5,5 0,0 1,220 695L220,505A5,5 0,0 1,225 500z"
android:strokeWidth="5"
android:strokeColor="#00000000"
android:strokeLineCap="round">
<aapt:attr name="android:fillColor">
<gradient
android:startX="220"
android:startY="600"
android:endX="260"
android:endY="600"
android:type="linear">
<item android:offset="0" android:color="#FF595959"/>
<item android:offset="0.2" android:color="#FF1A1A1A"/>
<item android:offset="0.4" android:color="#FF333333"/>
<item android:offset="1" android:color="#FFA6A6A6"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M45,500L75,500A5,5 0,0 1,80 505L80,695A5,5 0,0 1,75 700L45,700A5,5 0,0 1,40 695L40,505A5,5 0,0 1,45 500z"
android:strokeWidth="5"
android:strokeColor="#00000000"
android:strokeLineCap="round">
<aapt:attr name="android:fillColor">
<gradient
android:startX="40"
android:startY="600"
android:endX="80"
android:endY="600"
android:type="linear">
<item android:offset="0" android:color="#FF000000"/>
<item android:offset="0.6" android:color="#FF262626"/>
<item android:offset="0.8" android:color="#FF333333"/>
<item android:offset="1" android:color="#FF595959"/>
</gradient>
</aapt:attr>
</path>
</vector>
13 changes: 13 additions & 0 deletions app/src/main/res/drawable/mic_clamp_wheel.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="30dp"
android:height="80dp"
android:viewportWidth="300"
android:viewportHeight="800">
<path
android:pathData="m150,450 l-6.27,6.27 -6.8,-5.7 -5.71,6.8 -7.27,-5.09 -5.09,7.27 -7.68,-4.44 -4.44,7.69 -8.05,-3.75 -3.75,8.04 -8.34,-3.04 -3.04,8.34 -8.57,-2.3 -2.3,8.57 -8.74,-1.54 -1.54,8.74 -8.84,-0.77 -0.77,8.84h-8.87v8.88l-8.84,0.77 0.77,8.84 -8.74,1.54 1.54,8.74 -8.57,2.29 2.3,8.57 -8.34,3.04 3.04,8.34 -8.04,3.75 3.75,8.05 -7.69,4.44 4.44,7.68 -7.27,5.09 5.09,7.27 -6.8,5.7 5.7,6.8 -6.27,6.27 6.27,6.27 -5.7,6.8 6.8,5.7 -5.09,7.27 7.27,5.09 -4.44,7.69 7.68,4.44 -3.75,8.04 8.04,3.75 -3.04,8.34 8.34,3.04 -2.29,8.57 8.57,2.3 -1.54,8.74 8.74,1.54 -0.77,8.84 8.84,0.77v8.87h8.87l0.77,8.84 8.84,-0.77 1.54,8.74 8.74,-1.54 2.3,8.57 8.57,-2.3 3.04,8.34 8.34,-3.03 3.75,8.04 8.05,-3.75 4.44,7.68 7.68,-4.44 5.09,7.27 7.27,-5.09 5.71,6.8 6.8,-5.7 6.27,6.27 6.27,-6.27 6.8,5.7 5.71,-6.8 7.27,5.09 5.09,-7.27 7.68,4.44 4.44,-7.68 8.04,3.75 3.75,-8.05 8.34,3.04 3.04,-8.34 8.57,2.29 2.3,-8.57 8.74,1.54 1.54,-8.74 8.84,0.77 0.77,-8.84h8.87v-8.87l8.84,-0.77 -0.77,-8.84 8.74,-1.54 -1.54,-8.74 8.57,-2.29 -2.3,-8.57 8.34,-3.03 -3.04,-8.34 8.05,-3.75 -3.75,-8.04 7.68,-4.44 -4.44,-7.69 7.27,-5.09 -5.09,-7.27 6.8,-5.7 -5.7,-6.8 6.27,-6.27 -6.27,-6.27 5.7,-6.8 -6.8,-5.7 5.09,-7.27 -7.27,-5.09 4.44,-7.68 -7.69,-4.44 3.75,-8.05 -8.04,-3.75 3.03,-8.34 -8.34,-3.04 2.3,-8.57 -8.57,-2.3 1.54,-8.74 -8.74,-1.54 0.77,-8.84 -8.84,-0.77v-8.88h-8.87l-0.77,-8.84 -8.84,0.77 -1.54,-8.74 -8.74,1.54 -2.3,-8.57 -8.57,2.29 -3.04,-8.34 -8.34,3.04 -3.75,-8.04 -8.04,3.75 -4.44,-7.68 -7.68,4.44 -5.09,-7.27 -7.27,5.09 -5.71,-6.8 -6.8,5.7z"
android:strokeLineJoin="round"
android:strokeWidth="35.3553"
android:fillColor="#333333"
android:strokeColor="#00000000"/>
</vector>
Loading

0 comments on commit 7bac72d

Please sign in to comment.