Generate sound frequency in windows - VB.Net - vb.net

i need to generate a square wave sound in windows . I'm using this code :
System.console.beep(500,500)
But it don't works very well : It takes a bit to play the sound .
I have a 2.7 GHZ CPU , so i don't think my computer is slow .
Does someone know a library or another code to play frequencies in windows ?

Imports:
Imports System.IO
Imports System.Media
Call:
FrequencyBeep(500, 500, 10000)
Sub:
Public Shared Sub FrequencyBeep(ByVal Amplitude As Integer, ByVal Frequency As Integer, ByVal Duration As Integer)
Dim A As Double = ((Amplitude * (System.Math.Pow(2, 15))) / 1000) - 1
Dim DeltaFT As Double = 2 * Math.PI * Frequency / 44100.0
Dim Samples As Integer = 441 * Duration / 10
Dim Bytes As Integer = Samples * 4
Dim Hdr As Integer() = {1179011410, 36 + Bytes, 1163280727, 544501094, 16, 131073, 44100, 176400, 1048580, 1635017060, Bytes}
Using MS As MemoryStream = New MemoryStream(44 + Bytes)
Using BW As BinaryWriter = New BinaryWriter(MS)
For I As Integer = 0 To Hdr.Length - 1
BW.Write(Hdr(I))
Next
For T As Integer = 0 To Samples - 1
Dim Sample As Short = System.Convert.ToInt16(A * Math.Sin(DeltaFT * T))
BW.Write(Sample)
BW.Write(Sample)
Next
BW.Flush()
MS.Seek(0, SeekOrigin.Begin)
Using SP As SoundPlayer = New SoundPlayer(MS)
SP.PlaySync()
End Using
End Using
End Using
End Sub

Related

I need to increase the CPU usage of my program in VB.net

I have a program that take an image and changes it to 1 bit B&W. It uses Lockbyte software to make it faster. BUT, when running it, it takes over a minute to process one image. When looking at the CPU usage it is only 5% at most once it is running. Is there a way to get the computer to use more CPU time? The indicator is showing that the computer is running below 50%, as low as 25%.
I just had one DUH thought, I forgot to add the resizing function into my program. It should help but I know I need to make the conversion faster yet. The program will be used to do 100 to 300 images per batch.
Most other programs I have seen do a conversion within a few seconds per image. I would like to get to something like this too.
This is the program. Mostly cobbled together from samples. I only half understand it but can read it. Sorry to the contributors that I cannot give credit to them. I didn't keep track of them.
Public Class Form1
Public Shared Function ConvertTo1Bit(ByVal input As Bitmap) As Bitmap
Dim masks = New Byte() {&H80, &H40, &H20, &H10, &H8, &H4, &H2, &H1}
Dim output = New Bitmap(input.Width, input.Height, PixelFormat.Format1bppIndexed)
Dim data = New SByte(input.Width - 1, input.Height - 1) {}
Dim inputData = input.LockBits(New Rectangle(0, 0, input.Width, input.Height), ImageLockMode.[ReadOnly], PixelFormat.Format24bppRgb)
Try
Dim scanLine = inputData.Scan0
Dim line = New Byte(inputData.Stride - 1) {}
Dim y = 0
While y < inputData.Height
Marshal.Copy(scanLine, line, 0, line.Length)
For x = 0 To input.Width - 1
data(x, y) = CSByte((64 * (GetGreyLevel(line(x * 3 + 2), line(x * 3 + 1), line(x * 3 + 0)) - 0.5)))
Next
y += 1
scanLine += inputData.Stride
End While
Finally
input.UnlockBits(inputData)
End Try
Dim outputData = output.LockBits(New Rectangle(0, 0, output.Width, output.Height), ImageLockMode.[WriteOnly], PixelFormat.Format1bppIndexed)
Try
Dim scanLine = outputData.Scan0
Dim y = 0
While y < outputData.Height
Dim line = New Byte(outputData.Stride - 1) {}
For x = 0 To input.Width - 1
Dim j = data(x, y) > 0
Try
If j Then
line(x / 8) = line(x / 8) Or masks(x Mod 8)
End If
Catch ex As Exception
End Try
Dim [error] = CSByte((data(x, y) - (If(j, 32, -32))))
If x < input.Width - 1 Then data(x + 1, y) += CSByte((7 * [error] / 16))
If y < input.Height - 1 Then
If x > 0 Then data(x - 1, y + 1) += CSByte((3 * [error] / 16))
data(x, y + 1) += CSByte((5 * [error] / 16))
If x < input.Width - 1 Then data(x + 1, y + 1) += CSByte((1 * [error] / 16))
End If
Next
Marshal.Copy(line, 0, scanLine, outputData.Stride)
y += 1
scanLine += outputData.Stride
End While
Finally
output.UnlockBits(outputData)
End Try
Return output
End Function
Public Shared Function GetGreyLevel(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte) As Double
Return (r * 0.299 + g * 0.587 + b * 0.114) / 255
End Function
Private Sub btBrowesIn_Click(sender As Object, e As EventArgs) Handles btBrowesIn.Click
FolderBrowserDialog1.ShowDialog()
tbInPic.Text = FolderBrowserDialog1.SelectedPath
End Sub
Private Sub btBrowesOut_Click(sender As Object, e As EventArgs) Handles btBrowesOut.Click
FolderBrowserDialog2.ShowDialog()
tbInPic.Text = FolderBrowserDialog2.SelectedPath
End Sub
Private Sub btGo_Click(sender As Object, e As EventArgs) Handles btGo.Click
Dim Infiles As Array
Dim opf As New OpenFileDialog
opf.Filter = "Choose Image(*.jpg;*.png;*.gif)|*.jpg;*.png;*.gif"
If opf.ShowDialog = DialogResult.OK Then
PictureBox1.Image = Image.FromFile(opf.FileName)
Dim MyBitmap As New Bitmap(PictureBox1.Image)
PictureBox2.Image = ConvertTo1Bit(MyBitmap)
End If
End Sub
End Class
The program will be used to do 100 to 300 images per batch.
You can process the images asynchronously. .Net provides several ways to do this: Async/Await, raw Tasks, ThreadPool, raw Threads, BackgroundWorker, probably more. Which is most appropriate here depends on the context of the application.

Show only three significant digits for the data volume

how can I Show only three significant digits for the data volume, i.e. 0,xxx; x,xx; xx,x; xxx; x’xxx etc.
this is my code
Option Strict On
Imports System.Globalization
Module Module1
Public Function BytesToMegabytes(Bytes As Long) As String
'This function gives an estimate to two decimal
'places. For a more precise answer, format to
'more decimal places or just return dblAns
Dim dblAns As Double = (Bytes / 1024) / 1024
Dim ci = New CultureInfo("en-GB")
ci.NumberFormat.NumberDecimalSeparator = "'"
Return dblAns.ToString("###,###,##0.00", ci)
End Function
Sub Main()
Console.WriteLine(BytesToMegabytes(9225936896))
Console.ReadLine()
End Sub
End Module
Outputs:
currently I score 8,798'54 MB.
to be 8'798 MB, how can I get it?
thank you all for your help
Following on from your previous question...
To use significant figures instead of decimal places:
Public Function BytesToMegabytes(bytes As Long) As String
Dim dblAns As Double = (bytes / 1024) / 1024
If dblAns = 0 Then
Return "0"
End If
Dim significantFigures = 3
Dim magnitude = Math.Floor(Math.Log10(dblAns))
Dim v As Double = 10 ^ (magnitude - significantFigures + 1)
dblAns = Math.Floor(dblAns / v) * v
Dim ci = New CultureInfo("")
ci.NumberFormat.NumberDecimalSeparator = ","
ci.NumberFormat.NumberGroupSeparator = "'"
Return dblAns.ToString("#,##0.###", ci)
End Function
For example, Console.WriteLine(BytesToMegabytes(9225936896)) outputs
8'790
If you change the line Dim significantFigures = 3 to Dim significantFigures = 4, it outputs
8'798
Depending on the rounding you want, you may want to use dblAns = Math.Round(dblAns / v, MidpointRounding.AwayFromZero) * v instead, or perhaps Math.Ceiling instead of Math.Floor.

Visual Basic Threading with More than 2 Threads

I am currently trying to produce a sound using a custom beep class. One of the methods of the beep class is to produce multiple octaves of a sound with a given frequency, so one sound is the frequency, another is the frequency * 2, another is the frequency * 4, etc.
I am attempting to use threading to make these all sound together by giving each sound its own thread. However, I notice that it still plays sounds once-at-a-time. I can confirm that the sounds are not interrupting the flow of the program itself, however, so the threading is working in that capacity.
Here is the code I am using. The idea is that for NumOctave times, a new frequency is generated based off the first (and amplitude), and is set to sound in its own thread. However, it appears that the threads are queuing, rather than truly executing asynchronously from each other. What would be the best way to get the intended behavior?
Shared Sub OctBeep(ByVal Amplitude As Integer,
ByVal Frequency As Integer, ByVal NumOctaves As Integer,
ByVal Duration As Integer, ByVal NewThread As Boolean)
Dim threads As List(Of Thread) = New List(Of Thread)
Dim powTwo As Integer = 1
Dim powTen As Integer = 1
For oct As Integer = 1 To NumOctaves
Dim thisOct As Integer = oct
Dim thisThread As New Thread(
Sub()
Dim newFreq, newAmp As Integer
newFreq = Frequency * powTwo
newAmp = Amplitude / powTen
BeepHelp(newAmp, newFreq, Duration)
End Sub
)
thisThread.IsBackground = True
thisThread.Start()
powTwo *= 2
powTen *= 10
Next
End Sub
Here is BeepHelp()
Shared Sub BeepHelp(ByVal Amplitude As Integer,
ByVal Frequency As Integer,
ByVal Duration As Integer)
Dim A As Double = ((Amplitude * 2 ^ 15) / 1000) - 1
Dim DeltaFT As Double = 2 * Math.PI * Frequency / 44100
Dim Samples As Integer = 441 * Duration \ 10
Dim Bytes As Integer = Samples * 4
Dim Hdr() As Integer = {&H46464952, 36 + Bytes, &H45564157,
&H20746D66, 16, &H20001, 44100,
176400, &H100004, &H61746164, Bytes}
Using MS As New MemoryStream(44 + Bytes)
Using BW As New BinaryWriter(MS)
For I As Integer = 0 To Hdr.Length - 1
BW.Write(Hdr(I))
Next
For T As Integer = 0 To Samples - 1
Dim Sample As Short = CShort(A * Math.Sin(DeltaFT * T))
BW.Write(Sample)
BW.Write(Sample)
Next
BW.Flush()
MS.Seek(0, SeekOrigin.Begin)
Using SP As New SoundPlayer(MS)
SP.PlaySync()
End Using
End Using
End Using
End Sub
End Class
I ran into this same issue before writing a speech synthesizer class. There is a difference between Multi-threading(Just moves to a different thread so main program still works) & Parallel Processing(Moves the process to its own processor). You want to look into Parallel Processing instead

Using Logo to draw sound

I'm using Logo right now and i'm making a project and basically i want to turn your recorded voice into something visual, only problem is when i go to find code it re that works it requires 1: A picture box and 2: to manually grab the sound .wav file and place it. I already made code to record my voice and to make it into a .Wav file and i already have code to visualize it, just when i run it it appears as a thick square of lines rather than the example i shown. Note: I'm not drawing into a picturebox, i'm drawing directly into the Form by using g.drawline(bleh,bleh,bleh,bleh).
(Example: http://static1.1.sqspcdn.com/static/f/335152/16812948/1330286658510/76_dsc3616.jpeg?token=R1zPNnr9PAoB3WvnDxfFFFvzkMw%3D )
The code im trying to run:
Public Sub DrawSound(x As Integer, y As Integer)
Dim samplez As New List(Of Short)
Dim maxamount As Short
Dim pic As New Bitmap(x, y)
Dim ratio As Integer = (samplez.Count - 1) / (y - 1) 'If there are 10000 samples and 200 pixels, this would be every 50th sample is shown
Dim halfpic As Integer = (x / 2) 'Simply half the height of the picturebox
GC.Collect()
Dim wavefile() As Byte = IO.File.ReadAllBytes("C:\Users\" & Environ$("Username") & "\Documents\Sounds\Mic.wav")
GC.Collect()
Dim memstream As New IO.MemoryStream(wavefile)
Dim binreader As New IO.BinaryReader(memstream)
Dim ChunkID As Integer = binreader.ReadInt32()
Dim filesize As Integer = binreader.ReadInt32()
Dim rifftype As Integer = binreader.ReadInt32()
Dim fmtID As Integer = binreader.ReadInt32()
Dim fmtsize As Integer = binreader.ReadInt32()
Dim fmtcode As Integer = binreader.ReadInt16()
Dim channels As Integer = binreader.ReadInt16()
Dim samplerate As Integer = binreader.ReadInt32()
Dim fmtAvgBPS As Integer = binreader.ReadInt32()
Dim fmtblockalign As Integer = binreader.ReadInt16()
Dim bitdepth As Integer = binreader.ReadInt16()
If fmtsize = 18 Then
Dim fmtextrasize As Integer = binreader.ReadInt16()
binreader.ReadBytes(fmtextrasize)
End If
Dim DataID As Integer = binreader.ReadInt32()
Dim DataSize As Integer = binreader.ReadInt32()
samplez.Clear()
For i = 0 To (DataSize - 3) / 2
samplez.Add(binreader.ReadInt16())
If samplez(samplez.Count - 1) > maxamount Then 'Using this for the pic
maxamount = samplez(samplez.Count - 1)
End If
Next
For i = 1 To x - 10 Step 2 'Steping 2 because in one go, we do 2 samples
Dim leftdata As Integer = Math.Abs(samplez(i * ratio)) 'Grabbing that N-th sample to display. Using Absolute to show them one direction
Dim leftpercent As Single = leftdata / (maxamount * 2) 'This breaks it down to something like 0.0 to 1.0. Multiplying by 2 to make it half.
Dim leftpicheight As Integer = leftpercent * x 'So when the percent is tied to the height, its only a percent of the height
g.DrawLine(Pens.LimeGreen, i, halfpic, i, leftpicheight + halfpic) 'Draw dat! The half pic puts it in the center
Dim rightdata As Integer = Math.Abs(samplez((i + 1) * ratio)) 'Same thing except we're grabbing i + 1 because we'd skip it because of the 'step 2' on the for statement
Dim rightpercent As Single = -rightdata / (maxamount * 2) 'put a negative infront of data so it goes down.
Dim rightpicheight As Integer = rightpercent * x
g.DrawLine(Pens.Blue, i, halfpic, i, rightpicheight + halfpic)
Next
End Sub
X and Y is the middle of the form. And i also would link where i got the code but i forgot where and also, i modified it in attempt to run it directly into he form rather than a picturebox. It worked sorta haha (And there is so many unused dims but all i know is, once i remove one none of the code works haha) So could anyone help?

How to create circe whit GMap in VB.Net

I'm looking for some function which can create a circle on map. I'm using Gmap library in VB.Net. Exist some function which can create a circle around of point on map, for examle with 500 meters radius ?
I found a code, but it isn't what I'm exactly looking for :
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports GMap.NET
Imports GMap.NET.WindowsForms
Namespace Map
Public Class GMapMarkerCircle
Inherits GMapMarker
Private m_Radius As Integer
'In Meters
Public m_OutlinePen As Pen
Public m_FillBrush As Brush
Public m_Fill As Boolean
Public Sub New(p As PointLatLng, Radius As Integer, OutlinePen As Pen, FillBrush As Brush, Fill As Boolean)
MyBase.New(p)
m_OutlinePen = OutlinePen
m_FillBrush = FillBrush
m_Radius = Radius
m_Fill = Fill
End Sub
Public Overrides Sub OnRender(g As Graphics)
g.SmoothingMode = SmoothingMode.AntiAlias
Dim R As Integer = CInt((m_Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution(Overlay.Control.Zoom, Position.Lat)) * 2
If m_Fill = True Then
g.FillEllipse(m_FillBrush, New System.Drawing.Rectangle(LocalPosition.X - R \ 2, LocalPosition.Y - R \ 2, R, R))
End If
g.DrawEllipse(m_OutlinePen, New System.Drawing.Rectangle(LocalPosition.X - R \ 2, LocalPosition.Y - R \ 2, R, R))
End Sub
End Class
End Namespace
And in app:
Dim CircleMarker As New GMapMarkerCircle(New GMap.NET.PointLatLng(ZemSirka, ZemDlzka), 660, New Pen(Color.Azure, 1), Brushes.LightSeaGreen, True)
Dim Overlay As New GMapOverlay("Circle")
Overlay.Markers.Add(CircleMarker)
GMapControl1.Overlays.Add(Overlay)
But when I zoom in/out the map circle disappears.
I have one beginners question: is any possibility to do Brushes semitransparent ?
Finally I create code which works fine for short distances for examle: 200,300,500 meters.
Public Function toRad(ByVal deegres As Double)
Return deegres * (Math.PI / 180)
End Function
Public Function toDeg(ByVal radians As Double)
Return radians * (180 / Math.PI)
End Function
Private Function pivotRadius(ByVal Dlzka As Double, ByVal Sirka As Double, ByVal dist As Double)
Dim distance = (dist / earthRadius) / 1000
Dim lat As Double = toRad(Sirka)
Dim lng As Double = toRad(Dlzka)
Dim points As IList(Of PointLatLng) = New List(Of PointLatLng)()
Dim x As Integer = 0
While x < 360
Dim brng As Double = toRad(x)
Dim latRadians As Double = Math.Asin(Math.Sin(lat) * Math.Cos(distance) + Math.Cos(lat) * Math.Sin(distance) * Math.Cos(brng))
Dim lngRadians As Double = lng + (Math.Atan2(Math.Sin(brng) * Math.Sin(distance) * Math.Cos(lat), Math.Cos(distance) - Math.Sin(lat) * Math.Sin(latRadians)) / 1.6)
points.Add(New PointLatLng(toDeg(lngRadians), toDeg(latRadians)))
latRadians = 0
lngRadians = 0
x += 10
End While
Dim polyOverlay As New GMapOverlay("polygons")
Dim polygon As New GMapPolygon(points, "mypolygon")
polygon.Fill = New SolidBrush(Color.FromArgb(30, Color.Aqua))
polygon.Stroke = New Pen(Color.Blue, 1)
GMapControl1.Overlays.Clear()
GMapControl1.Overlays.Add(polyOverlay)
polyOverlay.Polygons.Add(polygon)
Return 0
End Function