After some search and reading the Graphics class document, I can't find a way to specify the line style of a line. I mean whether the line is a solid one or a dotted one. Could anybody help me?
Thanks!
You can't, well, not just by using Flex library classes anyway. You can do it yourself though, of course. Here's a class that implements it (modified from code found here, thanks Ken Fox):
/*Copyright (c) 2006 Adobe Systems Incorporated
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
package com.some.package {
import mx.graphics.IStroke;
import flash.display.Graphics;
public class GraphicsUtils {
public static function _drawDashedLine( target:Graphics, strokes:Array, pattern:Array,
drawingState:DashStruct,
x0:Number, y0:Number, x1:Number, y1:Number):void {
var dX:Number = x1 - x0;
var dY:Number = y1 - y0;
var len:Number = Math.sqrt( dX * dX + dY * dY );
dX /= len;
dY /= len;
var tMax:Number = len;
var t:Number = -drawingState.offset;
var patternIndex:int = drawingState.patternIndex;
var strokeIndex:int = drawingState.strokeIndex;
var styleInited:Boolean = drawingState.styleInited;
while( t < tMax ) {
t += pattern[patternIndex];
if( t < 0 ) {
var x:int = 5;
}
if( t >= tMax ) {
drawingState.offset = pattern[patternIndex] - ( t - tMax );
drawingState.patternIndex = patternIndex;
drawingState.strokeIndex = strokeIndex;
drawingState.styleInited = true;
t = tMax;
}
if( styleInited == false ) {
(strokes[strokeIndex] as IStroke).apply( target );
}
else {
styleInited = false;
}
target.lineTo( x0 + t * dX, y0 + t * dY );
patternIndex = ( patternIndex + 1 ) % pattern.length;
strokeIndex = ( strokeIndex + 1 ) % strokes.length;
}
}
public static function drawDashedLine( target:Graphics, strokes:Array, pattern:Array,
x0:Number, y0:Number, x1:Number, y1:Number ):void {
target.moveTo( x0, y0 );
var struct:DashStruct = new DashStruct();
_drawDashedLine( target, strokes, pattern, struct, x0, y0, x1, y1 );
}
public static function drawDashedPolyLine( target:Graphics, strokes:Array, pattern:Array,
points:Array ):void {
if( points.length == 0 ) { return; }
var prev:Object = points[0];
var struct:DashStruct = new DashStruct();
target.moveTo( prev.x, prev.y );
for( var i:int = 1; i < points.length; i++ ) {
var current:Object = points[i];
_drawDashedLine( target, strokes, pattern, struct,
prev.x, prev.y, current.x, current.y );
prev = current;
}
}
}
}
class DashStruct {
public function init():void {
patternIndex = 0;
strokeIndex = 0;
offset = 0;
}
public var patternIndex:int = 0;
public var strokeIndex:int = 0;
public var offset:Number = 0;
public var styleInited:Boolean = false;
}
And you can use it like:
var points:Array = [];
points.push( { x: 0, y: 0 } );
points.push( { x: this.width, y: 0 } );
points.push( { x: this.width, y: this.height } );
points.push( { x: 0, y: this.height } );
points.push( { x: 0, y: 0 } );
var strokes:Array = [];
var transparentStroke:Stroke = new Stroke( 0x0, 0, 0 );
strokes.push( new Stroke( 0x999999, 2, 1, false, 'normal', CapsStyle.NONE ) );
strokes.push( transparentStroke );
strokes.push( new Stroke( 0x222222, 2, 1, false, 'normal', CapsStyle.NONE ) );
strokes.push( transparentStroke );
GraphicsUtils.drawDashedPolyLine( this.graphics, strokes, [ 16, 5, 16, 5 ], points );
Well there is no Dashed or Dotted line in flex.
However, you can create your own line or border:
http://cookbooks.adobe.com/post_Creating_a_dashed_line_custom_border_with_dash_and-13286.html
Try and enjoy!
I ran across this, today, which I like a lot. Provides for dashed/dotted lines and a few other things (curves, primarily).
http://flexdevtips.blogspot.com/2010/01/drawing-dashed-lines-and-cubic-curves.html
I wrote some simple DashedLine code -
import flash.display.Graphics;
import spark.primitives.Line;
public class DashedLine extends Line
{
public var dashLength:Number = 10;
override protected function draw(g:Graphics):void
{
// Our bounding box is (x1, y1, x2, y2)
var x1:Number = measuredX + drawX;
var y1:Number = measuredY + drawY;
var x2:Number = measuredX + drawX + width;
var y2:Number = measuredY + drawY + height;
var isGap:Boolean;
// Which way should we draw the line?
if ((xFrom <= xTo) == (yFrom <= yTo))
{
// top-left to bottom-right
g.moveTo(x1, y1);
x1 += dashLength;
for(x1; x1 < x2; x1 += dashLength){
if(isGap){
g.moveTo(x1, y1);
} else {
g.lineTo(x1, y1);
}
isGap = !isGap;
}
}
else
{
// bottom-left to top-right
g.moveTo(x1, y2);
x1 += dashLength;
for(x1; x1 < x2; y2 += dashLength){
if(isGap){
g.moveTo(x1, y2);
} else {
g.lineTo(x1, y2);
}
isGap = !isGap;
}
}
}
}
Then use it like this -
<comps:DashedLine top="{}" left="0" width="110%" >
<comps:stroke>
<s:SolidColorStroke color="0xff0000" weight="1"/>
</comps:stroke>
</comps:DashedLine>
I do it pretty simple:
public static function drawDottedLine(target:Graphics, xFrom:Number, yFrom:Number, xTo:Number, yTo:Number, dotLenth:Number = 10):void{
var isGap:Boolean;
target.moveTo(xFrom, yFrom);
xFrom += dotLenth;
for(xFrom; xFrom < xTo; xFrom += dotLenth){
if(isGap){
target.moveTo(xFrom, yFrom);
} else {
target.lineTo(xFrom, yFrom);
}
isGap = !isGap;
}
}
UPD: :) The same way as in the link provided by Ross.
Related
I am building a component that will display any image inside a parent div and allows dragging of the image (when larger than the div) as well as scaling on both a double click or pinch on mobile. I am using inline style changes on the image to test the behavior and so far everything works as I wanted...except that when I change the image transform:scale() all the calculations that effectively set the correct limits to prevent offsetting an image outside the parent div no longer behave as expected. It does work perfectly if I keep the scale=1.
So for example, with a parent Div width and height of 500/500 respectively, and an image that say is 1500x1000, I prevent any "over"offsetting when dragging the image by setting limits of leftLimit = -(1500-500) = -1000 and topLimit = -(1000-500) = -500. This works perfectly at the initial scale of 1. However, I have a dblClick event that scales the image upwards at .5 intervals, and once the scale changes from 1 to any other number, the methods I use above to calculate offset Limits are no longer value. So for example if I increase the scale to 2, in theory that same 1500x1000 image in a 500x500 div should NOW have leftLimit = -(3000-500) = -2500 and topLimit = -(2000-500) = 1500. But these new calculated limits allow the image to be dragged right out of the parent div region. For reference here is the code. Any help or methods for testing what's actually going on would be very much appreciated.
Note the image is being loaded as a file for test, it's a fairly large base64 string. The code is as follows (btw, I am figuring my use of so many 'state' variables probably exposes my ignorance of how such values could/should really persist across renderings. I am still quite new to React) :
import * as React from 'react'
import * as types from '../../types/rpg-types'
import imgSource from './testwebmap.jpg'
import * as vars from '../../data/mapImage'
const testImg = require('./testwebmap.jpg')
export default function MyMapImage() {
let divRef = React.useRef<HTMLDivElement>(null)
let imgRef = React.useRef<HTMLImageElement>(null)
const [loaded, setLoaded] = React.useState<boolean>(false)
const [imgTop, setImgTop] = React.useState<number>(0)
const [imgLeft, setImgLeft] = React.useState<number>(0)
const [scHeight, setSCHeight] = React.useState<number>(100)
const [scWidth, setSCWidth] = React.useState<number>(100)
const [imgScale, setImgScale] = React.useState<number>(1)
const [natHeight, setNatHeight] = React.useState<number>(100)
const [natWidth, setNatWidth] = React.useState<number>(100)
const [oldXCoord, setOldXCoord] = React.useState<number>(0)
const [oldYCoord, setOldYCoord] = React.useState<number>(0)
const [topLimit, setTopLimit] = React.useState<number>(0)
const [leftLimit, setLeftLimit] = React.useState<number>(0)
const [isScaling, setIsScaling] = React.useState<boolean>(false)
const [isDragging, setIsDragging] = React.useState<boolean>(false)
const [isFirstPress, setIsFirstPress] = React.useState<boolean>(false)
const [accel, setAccel] = React.useState<number>(1)
const [touchDist, setTouchDist] = React.useState<number>(0)
const [cfg, setCfg] = React.useState<types.ImageConfig>({
img: '',
imgTOP: 0,
imgLEFT: 0,
offsetX: 0,
offsetY: 0,
isFirstPress: true,
isDragging: false,
isScaling: false,
divHeight: 500,
divWidth: 500,
topLimit: 0,
leftLimit: 0,
isLoaded: true,
oldMouseX: 0,
oldMouseY: 0,
touchDist: 0,
})
const setNewImageLimits = () => {
const img = imgRef
let heightLimit: number
let widthLimit: number
console.log(`imgScale is: ${imgScale}`)
//console.log(`current offsets: ${imgLeft}:${imgTop}`)
console.log(`img width/Height: ${img.current?.width}:${img.current?.height}`)
console.log(img)
img.current
? (heightLimit = Math.floor(imgScale * img.current.naturalHeight - cfg.divHeight))
: (heightLimit = 0)
img.current
? (widthLimit = Math.floor(imgScale * img.current.naturalWidth - cfg.divWidth))
: (widthLimit = 0)
setTopLimit(-heightLimit)
setLeftLimit(-widthLimit)
setImgLeft(0)
setImgTop(0)
console.log(
'New Image limits set with topLimit:' + heightLimit + ' and leftLimit:' + widthLimit
)
}
const handleImageLoad = () => {
if (imgRef) {
const img = imgRef
//console.log(imgRef)
let heightLimit: number
let widthLimit: number
img.current ? (heightLimit = img.current.naturalHeight - cfg.divHeight) : (heightLimit = 0)
img.current ? (widthLimit = img.current.naturalWidth - cfg.divWidth) : (widthLimit = 0)
setTopLimit(-heightLimit)
setLeftLimit(-widthLimit)
setNatHeight(img.current ? img.current.naturalHeight : 0)
setNatWidth(img.current ? img.current.naturalWidth : 0)
setSCHeight(img.current ? img.current.naturalHeight : 0)
setSCWidth(img.current ? img.current.naturalWidth : 0)
console.log('Image Loaded with topLimit:' + heightLimit + ' and leftLimit:' + widthLimit)
}
}
React.useEffect(() => {
if (imgRef.current?.complete) {
handleImageLoad()
}
}, [])
React.useEffect(() => {
setNewImageLimits()
console.log(`imgScale is: ${imgScale}`)
console.log('Image has with topLimit:' + topLimit + ' and leftLimit:' + leftLimit)
}, [imgScale])
function distance(e: any) {
let zw = e.touches[0].pageX - e.touches[1].pageX
let zh = e.touches[0].pageY - e.touches[1].pageY
if (zw * zw + zh * zh != 0) {
return Math.sqrt(zw * zw + zh * zh)
} else return 0
}
function setCoordinates(e: any) {
let canMouseX: number
let canMouseY: number
if (e?.nativeEvent?.clientX && e?.nativeEvent?.clientY) {
//console.log(e)
//canMouseX = parseInt(e.clientX - cfg.offsetX)
canMouseX = e.nativeEvent.clientX - cfg.offsetX
canMouseY = e.nativeEvent.clientY - cfg.offsetY
//console.log(`${canMouseX}:${canMouseY}`)
} else if (e?.nativeEvent?.targetTouches) {
canMouseX = e.nativeEvent.targetTouches.item(0)?.clientX - cfg.offsetX
canMouseY = e.nativeEvent.targetTouches.item(0)?.clientY - cfg.offsetY
// This isn't doing anything (noticeable)
// e.preventDefault();
} else return {}
return {
canMouseX,
canMouseY,
}
}
const handleMouseUp = (e: any) => {
let { canMouseX, canMouseY } = setCoordinates(e)
setIsScaling(false)
setIsDragging(false)
setIsFirstPress(true)
setAccel(1)
console.log('Mouse UP Event function')
}
const handleMouseDown = (e: any) => {
const { canMouseX, canMouseY } = setCoordinates(e)
//console.log('Mouse DOWN Event function')
e.preventDefault()
//console.log(`Mouse Down ${canMouseX}:${canMouseY}`)
canMouseX ? setOldXCoord(canMouseX) : setOldXCoord(0)
canMouseY ? setOldYCoord(canMouseY) : setOldYCoord(0)
setIsDragging(true)
setCfg({ ...cfg, isDragging: true })
if (e?.targetTouches) {
e.preventDefault()
if (e?.nativeEvent?.touches?.length > 1) {
// detected a pinch
setTouchDist(distance(e))
setCfg({ ...cfg, touchDist: distance(e), isScaling: true })
setIsScaling(true)
setIsDragging(false)
} else {
// set the drag flag
setIsScaling(false)
setIsDragging(true)
}
}
setIsFirstPress(false)
setCfg({ ...cfg, isFirstPress: true })
}
const handleDoubleClick = (e: any) => {
const { canMouseX, canMouseY } = setCoordinates(e)
if (imgScale === 3) {
setImgScale(1)
} else {
setImgScale(imgScale + 0.5)
}
}
const handleMouseMove = (e: any) => {
let scaling = isScaling
let dragging = isDragging
let tempImgScale: number = 1
const { canMouseX, canMouseY } = setCoordinates(e)
let yDiff: number
let xDiff: number
let newLeft: number
let newTop: number
if (e.targetTouches) {
e.preventDefault()
if (e.touches.length > 1) {
//detected a pinch
setIsScaling(true)
setIsDragging(false)
scaling = true
} else {
setIsScaling(false)
setIsDragging(true)
}
}
//console.log(`isScaling : ${isScaling}`)
if (scaling) {
//...adding rndScaleTest to force processing of scaling randomly
let dist = distance(e)
//Can't divide by zero, so return dist in denom. if touchDist still at initial 0 value
tempImgScale = dist / (touchDist === 0 ? dist : touchDist)
//console.log(`imgScale is: ${imgScale}`)
if (tempImgScale < 1) tempImgScale = 1 //for now no scaling down allowed...
if (tempImgScale > 2) tempImgScale = 2 //...and scaling up limited to 2.5x
setSCHeight(Math.floor(imgScale * natHeight))
setSCWidth(Math.floor(imgScale * natWidth))
setImgScale(tempImgScale)
setTouchDist(dist)
}
// if the drag flag is set, clear the canvas and draw the image
if (isDragging) {
yDiff = canMouseY && oldYCoord ? accel * (canMouseY - oldYCoord) : 0
xDiff = canMouseX && oldXCoord ? accel * (canMouseX - oldXCoord) : 0
if (imgLeft + xDiff <= leftLimit) {
setImgLeft(leftLimit)
} else if (imgLeft + xDiff >= 0) {
setImgLeft(0)
} else setImgLeft(imgLeft + xDiff)
if (imgTop + yDiff <= topLimit) {
setImgTop(topLimit)
} else if (imgTop + yDiff >= 0) {
setImgTop(0)
} else setImgTop(imgTop + yDiff)
if (accel < 4) {
setAccel(accel + 1)
}
}
//console.log('Mouse **MOVE Event function')
setOldXCoord(canMouseX || 0)
setOldYCoord(canMouseY || 0)
}
const handleMouseLeave = (e: any) => {
setIsScaling(false)
setIsDragging(false)
setIsFirstPress(true)
setAccel(1)
console.log('Mouse LEAVE Event function')
}
return (
<div>
<div className="portrait">
<div
ref={divRef}
className="wrapper"
onMouseUp={handleMouseUp}
onMouseMove={handleMouseMove}
onTouchEnd={handleMouseUp}
onMouseDown={handleMouseDown}
onTouchStart={handleMouseDown}
onTouchMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
onDoubleClick={handleDoubleClick}
>
<img
ref={imgRef}
src={`data:image/jpeg;base64,${vars.bigImage}`}
style={{
transform: `scale(${imgScale})`,
transformOrigin: `top left`,
objectPosition: `${imgLeft}px ${imgTop}px`,
}}
onLoad={handleImageLoad}
/>
</div>
</div>
<span>{`imgLeft: ${imgLeft}px `}</span>
<span>{`imgTop: ${imgTop}px `}</span>
</div>
)
}
In the end, the problem does lie with the use of Scale(), and I could not rely on it for purposes of tracking position and offset. So I ended up explicitly scaling 'height' and 'width' for the img and keeping the scaling value as a reference when required to calculate new values for these. The parent Div and Img essentially now look like this:
<div
ref={divRef}
className="wrapper"
onMouseUp={handleMouseUp}
onMouseMove={handleMouseMove}
onTouchEnd={handleMouseUp}
onMouseDown={handleMouseDown}
onTouchStart={handleMouseDown}
onTouchMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
onDoubleClick={handleDoubleClick}
>
<img
ref={imgRef}
src={`data:image/jpeg;base64,${vars.bigImage}`}
style={{
transform: `translate(${imgLeft}px, ${imgTop}px)`,
height: `${scHeight}px`,
width: `${scWidth}px)`,
transformOrigin: `top left`,
}}
onLoad={handleImageLoad}
/>
</div>
This works fine, calculated offsets match the expected values, and translation of the image within the parent div behaves as expected.
Hi im tryign to create a zigzag path using Path.js's onMouseDrag function but getting in to a bit of a muddle here is a sketch
and code
var path
var zigzag
var length
var count
var delta=[]
tool.fixedDistance= 20
function onMouseDown(event){
path= new Path()
path.add(event.point)
zigzag= new Path()
}
function onMouseDrag(event){
event.delta += 90
path.add(event.delta)
delta.push(event.delta)
}
function onMouseUp(event){
length= path.segments.length
zigzag= new Path()
zigzag.add(event.point)
console.log(delta)
delta.forEach(( zig , i) => {
zigzag.add(i % 2 == 0 ? zig + 20 : zig - 20)
})
zigzag.selected= true
}
Based on my previous answer, here is a sketch demonstrating a possible way to do it.
let line;
let zigZag;
function onMouseDown(event) {
line = new Path({
segments: [event.point, event.point],
strokeColor: 'black'
});
zigZag = createZigZagFromLine(line);
}
function onMouseDrag(event) {
line.lastSegment.point = event.point;
if (zigZag) {
zigZag.remove();
}
zigZag = createZigZagFromLine(line);
}
function createZigZagFromLine(line) {
const zigZag = new Path({ selected: true });
const count = 20, length = line.length;
for (let i = 0; i <= count; i++) {
const offset = i / count * length;
const normal = i === 0 || i === count
? new Point(0, 0)
: line.getNormalAt(offset) * 30;
const point = line.getPointAt(offset).add(i % 2 == 0 ? normal
: -normal);
zigZag.add(point);
}
return zigZag;
}
Say, I have an array of float points (function xy). The first image is trying with SkiaSharp, the second is with System.Drawing of .NET Framework.
I understand that I should use a method like CubicTo, but I don't see how to combine it to achieve the expected result.
The example was created in WindowsForms (only uses 2 PictureBox) and SkiaSharp nuget. It is similar with Xamarin, the question is the same.
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using SkiaSharp;
namespace SKLab
{
public partial class BasicTestForm : Form
{
float startX = -4, stopX = 4;
float yi = -4, ye = 4;
float w = 200, h = 150;
float stepX = 1;
float x, px;
float y, py;
// pixel to cartesian
float pixelFromX(float cartX) => w * (cartX - startX) / (stopX - startX);
// cartesian to pixel
float pixelFromY(float cartY) => h * (cartY - yi) / (ye - yi);
public BasicTestForm()
{
InitializeComponent();
SkiaPlot(pictureBox1);
DrawingPlot(pictureBox2);
}
private void SkiaPlot(PictureBox p)
{
p.Size = new Size((int)w, (int)h);
using (var surface = SKSurface.Create(new SKImageInfo(p.Width, p.Height))) {
SKCanvas g = surface.Canvas;
g.Clear(SKColors.White);
using (var paint = new SKPaint()) {
paint.Style = SKPaintStyle.Stroke;
paint.IsAntialias = true;
paint.Color = SKColors.CornflowerBlue;
paint.StrokeWidth = 2;
var path = new SKPath();
for (x = startX; x <= stopX; x += stepX) {
px = pixelFromX(x);
py = pixelFromY((float)Math.Sin(x));
if (x == startX) {
path.MoveTo(px, py);
} else {
path.LineTo(px, py);
}
}
g.DrawPath(path, paint);
}
using (SKImage image = surface.Snapshot())
using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100))
using (MemoryStream mStream = new MemoryStream(data.ToArray())) {
p.Image = new Bitmap(mStream, false);
}
}
}
void DrawingPlot(PictureBox p)
{
p.Size = new Size((int)w, (int)h); ;
// Make the Bitmap.
var canvas = new Bitmap(p.ClientSize.Width, p.ClientSize.Height);
using (var g = Graphics.FromImage(canvas)) {
// Clear.
g.Clear(Color.White);
// curve
var points = new List<PointF>();
for (x = startX; x <= stopX; x += stepX) {
points.Add(new PointF
{
X = pixelFromX(x),
Y = pixelFromY((float)Math.Sin(x))
});
}
g.SmoothingMode = SmoothingMode.AntiAlias;
using (var pen = new Pen(Color.CornflowerBlue, 2)) {
g.DrawCurve(pen, points.ToArray());
}
}
// Display the result.
p.Image = canvas;
}
}
}
I am using recorderWorker.js and recorder.js
The final output which i get from this code is 44.1khz, 2-channel (stereo) wav file.But my requirement is 8khz , 1-channel wav file.
How can i achieve this with the help of recorderWorker.js
Kindly help me to resolve the issue.
The code for recorderWorker.js is
var recLength = 0,
recBuffers = [],
sampleRate;
this.onmessage = function(e){
switch(e.data.command){
case 'init':
init(e.data.config);
break;
case 'record':
record(e.data.buffer);
break;
case 'exportWAV':
exportWAV(e.data.type);
break;
case 'getBuffer':
getBuffer();
break;
case 'clear':
clear();
break;
}
};
function init(config){
sampleRate = config.sampleRate;
}
function record(inputBuffer){
var bufferL = inputBuffer[0];
var bufferR = inputBuffer[1];
var interleaved = interleave(bufferL, bufferR);
recBuffers.push(interleaved);
recLength += interleaved.length;
}
function exportWAV(type){
var buffer = mergeBuffers(recBuffers, recLength);
var dataview = encodeWAV(buffer);
var audioBlob = new Blob([dataview], { type: type });
this.postMessage(audioBlob);
}
function getBuffer() {
var buffer = mergeBuffers(recBuffers, recLength)
this.postMessage(buffer);
}
function clear(){
recLength = 0;
recBuffers = [];
}
function mergeBuffers(recBuffers, recLength){
var result = new Float32Array(recLength);
var offset = 0;
for (var i = 0; i < recBuffers.length; i++){
result.set(recBuffers[i], offset);
offset += recBuffers[i].length;
}
return result;
}
function interleave(inputL, inputR){
var length = inputL.length + inputR.length;
var result = new Float32Array(length);
var index = 0,
inputIndex = 0;
while (index < length){
result[index++] = inputL[inputIndex];
result[index++] = inputR[inputIndex];
inputIndex++;
}
return result;
}
function floatTo16BitPCM(output, offset, input){
for (var i = 0; i < input.length; i++, offset+=2){
var s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
}
}
function writeString(view, offset, string){
for (var i = 0; i < string.length; i++){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
function encodeWAV(samples){
var buffer = new ArrayBuffer(44 + samples.length * 2);
var view = new DataView(buffer);
/* RIFF identifier */
writeString(view, 0, 'RIFF');
/* file length */
view.setUint32(4, 32 + samples.length * 2, true);
/* RIFF type */
writeString(view, 8, 'WAVE');
/* format chunk identifier */
writeString(view, 12, 'fmt ');
/* format chunk length */
view.setUint32(16, 16, true);
/* sample format (raw) */
view.setUint16(20, 1, true);
/* channel count */
view.setUint16(22, 2, true);
/* sample rate */
view.setUint32(24, sampleRate, true);
/* byte rate (sample rate * block align) */
view.setUint32(28, sampleRate * 4, true);
/* block align (channel count * bytes per sample) */
view.setUint16(32, 4, true);
/* bits per sample */
view.setUint16(34, 16, true);
/* data chunk identifier */
writeString(view, 36, 'data');
/* data chunk length */
view.setUint32(40, samples.length * 2, true);
floatTo16BitPCM(view, 44, samples);
return view;
}
You don't need to modify the Recorder.JS library - this functionality is already provided. The constructor accepts a config object as the second parameter, as below:
var audioContext = new AudioContext();
var microphone = audioContext.createMediaStreamSource(stream);
recorder = new Recorder(microphone, { numChannels: 1, sampleRate: 8000 });
Do I have make my own Point and Vector types to overload them ? Why does this not work ?
namespace System . windows
{
public partial struct Point : IFormattable
{
public static Point operator * ( Point P , double D )
{
Point Po = new Point ( );
return Po;
}
}
}
namespace SilverlightApplication36
{
public partial class MainPage : UserControl
{
public static void ShrinkingRectangle ( WriteableBitmap wBM , int x1 , int y1 , int x2 , int y2 , Color C )
{
wBM . DrawRectangle ( x1 , y1 , x2 , y2 , Colors . Red );
Point Center = Mean ( x1 , y1 , x2 , y2 );
wBM . SetPixel ( Center , Colors.Blue , 3 );
Point P1 = new Point ( x1 , y1 );
Point P2 = new Point ( x1 , y2 );
Point P3 = new Point ( x1 , y2 );
Point P4 = new Point ( x2 , y1 );
const int Steps = 10;
for ( int i = 0 ; i < Steps ; i++ )
{
double iF = (double)(i+1) / (double)Steps;
double jF = ( 1.0 - iF );
Point P11 = **P1 * jF;**
}
}
I don't really understand what you're trying to achieve with this line:
Point P11 = **P1 * jF;**
If you try to power it then use the Math.Pow function.
Update
You should have an internal field in the structure that represents your values, then implementing the operator is very easy.
As for the IFormattable, I didn't really test what I am writing, I just copied the code from here to give you the idea:
public partial struct Point : IFormattable
{
private double x;
public double X
{
get { return x; }
}
private double y;
public double Y
{
get { return y; }
}
public static Point operator *(Point point, double value)
{
return new Point(point.X * value, point.y * value);
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
#region IFormattable Members
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null) format = "H"; //hyphenized
if (formatProvider != null)
{
ICustomFormatter formatter =
(ICustomFormatter)formatProvider.GetFormat(this.GetType());
if (formatter != null)
return formatter.Format(format, this, formatProvider);
}
switch (format)
{
case "X:
return string.Format("{0}x{1}", X, Y);
case "C":
return string.Format("{0}, {1}", X, Y);
case "H":
default:
return string.Format("{0}-{1}", X, Y);
}
}
#endregion
}