Browse Source

Initial commit. That was a fun challenge!

Starbeamrainbowlabs 1 year ago
commit
37f310a1b1

+ 434
- 0
.gitignore View File

@@ -0,0 +1,434 @@
1
+
2
+# Created by https://www.gitignore.io/api/visualstudio,monodevelop,csharp
3
+
4
+### Csharp ###
5
+## Ignore Visual Studio temporary files, build results, and
6
+## files generated by popular Visual Studio add-ons.
7
+##
8
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
9
+
10
+# User-specific files
11
+*.suo
12
+*.user
13
+*.userosscache
14
+*.sln.docstates
15
+
16
+# User-specific files (MonoDevelop/Xamarin Studio)
17
+*.userprefs
18
+
19
+# Build results
20
+[Dd]ebug/
21
+[Dd]ebugPublic/
22
+[Rr]elease/
23
+[Rr]eleases/
24
+x64/
25
+x86/
26
+bld/
27
+[Bb]in/
28
+[Oo]bj/
29
+[Ll]og/
30
+
31
+# Visual Studio 2015 cache/options directory
32
+.vs/
33
+# Uncomment if you have tasks that create the project's static files in wwwroot
34
+#wwwroot/
35
+
36
+# MSTest test Results
37
+[Tt]est[Rr]esult*/
38
+[Bb]uild[Ll]og.*
39
+
40
+# NUNIT
41
+*.VisualState.xml
42
+TestResult.xml
43
+
44
+# Build Results of an ATL Project
45
+[Dd]ebugPS/
46
+[Rr]eleasePS/
47
+dlldata.c
48
+
49
+# .NET Core
50
+project.lock.json
51
+project.fragment.lock.json
52
+artifacts/
53
+**/Properties/launchSettings.json
54
+
55
+*_i.c
56
+*_p.c
57
+*_i.h
58
+*.ilk
59
+*.meta
60
+*.obj
61
+*.pch
62
+*.pdb
63
+*.pgc
64
+*.pgd
65
+*.rsp
66
+*.sbr
67
+*.tlb
68
+*.tli
69
+*.tlh
70
+*.tmp
71
+*.tmp_proj
72
+*.log
73
+*.vspscc
74
+*.vssscc
75
+.builds
76
+*.pidb
77
+*.svclog
78
+*.scc
79
+
80
+# Chutzpah Test files
81
+_Chutzpah*
82
+
83
+# Visual C++ cache files
84
+ipch/
85
+*.aps
86
+*.ncb
87
+*.opendb
88
+*.opensdf
89
+*.sdf
90
+*.cachefile
91
+*.VC.db
92
+*.VC.VC.opendb
93
+
94
+# Visual Studio profiler
95
+*.psess
96
+*.vsp
97
+*.vspx
98
+*.sap
99
+
100
+# TFS 2012 Local Workspace
101
+$tf/
102
+
103
+# Guidance Automation Toolkit
104
+*.gpState
105
+
106
+# ReSharper is a .NET coding add-in
107
+_ReSharper*/
108
+*.[Rr]e[Ss]harper
109
+*.DotSettings.user
110
+
111
+# JustCode is a .NET coding add-in
112
+.JustCode
113
+
114
+# TeamCity is a build add-in
115
+_TeamCity*
116
+
117
+# DotCover is a Code Coverage Tool
118
+*.dotCover
119
+
120
+# Visual Studio code coverage results
121
+*.coverage
122
+*.coveragexml
123
+
124
+# NCrunch
125
+_NCrunch_*
126
+.*crunch*.local.xml
127
+nCrunchTemp_*
128
+
129
+# MightyMoose
130
+*.mm.*
131
+AutoTest.Net/
132
+
133
+# Web workbench (sass)
134
+.sass-cache/
135
+
136
+# Installshield output folder
137
+[Ee]xpress/
138
+
139
+# DocProject is a documentation generator add-in
140
+DocProject/buildhelp/
141
+DocProject/Help/*.HxT
142
+DocProject/Help/*.HxC
143
+DocProject/Help/*.hhc
144
+DocProject/Help/*.hhk
145
+DocProject/Help/*.hhp
146
+DocProject/Help/Html2
147
+DocProject/Help/html
148
+
149
+# Click-Once directory
150
+publish/
151
+
152
+# Publish Web Output
153
+*.[Pp]ublish.xml
154
+*.azurePubxml
155
+# TODO: Comment the next line if you want to checkin your web deploy settings
156
+# but database connection strings (with potential passwords) will be unencrypted
157
+*.pubxml
158
+*.publishproj
159
+
160
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
161
+# checkin your Azure Web App publish settings, but sensitive information contained
162
+# in these scripts will be unencrypted
163
+PublishScripts/
164
+
165
+# NuGet Packages
166
+*.nupkg
167
+# The packages folder can be ignored because of Package Restore
168
+**/packages/*
169
+# except build/, which is used as an MSBuild target.
170
+!**/packages/build/
171
+# Uncomment if necessary however generally it will be regenerated when needed
172
+#!**/packages/repositories.config
173
+# NuGet v3's project.json files produces more ignorable files
174
+*.nuget.props
175
+*.nuget.targets
176
+
177
+# Microsoft Azure Build Output
178
+csx/
179
+*.build.csdef
180
+
181
+# Microsoft Azure Emulator
182
+ecf/
183
+rcf/
184
+
185
+# Windows Store app package directories and files
186
+AppPackages/
187
+BundleArtifacts/
188
+Package.StoreAssociation.xml
189
+_pkginfo.txt
190
+
191
+# Visual Studio cache files
192
+# files ending in .cache can be ignored
193
+*.[Cc]ache
194
+# but keep track of directories ending in .cache
195
+!*.[Cc]ache/
196
+
197
+# Others
198
+ClientBin/
199
+~$*
200
+*~
201
+*.dbmdl
202
+*.dbproj.schemaview
203
+*.jfm
204
+*.pfx
205
+*.publishsettings
206
+orleans.codegen.cs
207
+
208
+# Since there are multiple workflows, uncomment next line to ignore bower_components
209
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
210
+#bower_components/
211
+
212
+# RIA/Silverlight projects
213
+Generated_Code/
214
+
215
+# Backup & report files from converting an old project file
216
+# to a newer Visual Studio version. Backup files are not needed,
217
+# because we have git ;-)
218
+_UpgradeReport_Files/
219
+Backup*/
220
+UpgradeLog*.XML
221
+UpgradeLog*.htm
222
+
223
+# SQL Server files
224
+*.mdf
225
+*.ldf
226
+*.ndf
227
+
228
+# Business Intelligence projects
229
+*.rdl.data
230
+*.bim.layout
231
+*.bim_*.settings
232
+
233
+# Microsoft Fakes
234
+FakesAssemblies/
235
+
236
+# GhostDoc plugin setting file
237
+*.GhostDoc.xml
238
+
239
+# Node.js Tools for Visual Studio
240
+.ntvs_analysis.dat
241
+node_modules/
242
+
243
+# Typescript v1 declaration files
244
+typings/
245
+
246
+# Visual Studio 6 build log
247
+*.plg
248
+
249
+# Visual Studio 6 workspace options file
250
+*.opt
251
+
252
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
253
+*.vbw
254
+
255
+# Visual Studio LightSwitch build output
256
+**/*.HTMLClient/GeneratedArtifacts
257
+**/*.DesktopClient/GeneratedArtifacts
258
+**/*.DesktopClient/ModelManifest.xml
259
+**/*.Server/GeneratedArtifacts
260
+**/*.Server/ModelManifest.xml
261
+_Pvt_Extensions
262
+
263
+# Paket dependency manager
264
+.paket/paket.exe
265
+paket-files/
266
+
267
+# FAKE - F# Make
268
+.fake/
269
+
270
+# JetBrains Rider
271
+.idea/
272
+*.sln.iml
273
+
274
+# CodeRush
275
+.cr/
276
+
277
+# Python Tools for Visual Studio (PTVS)
278
+__pycache__/
279
+*.pyc
280
+
281
+# Cake - Uncomment if you are using it
282
+# tools/**
283
+# !tools/packages.config
284
+
285
+# Telerik's JustMock configuration file
286
+*.jmconfig
287
+
288
+# BizTalk build output
289
+*.btp.cs
290
+*.btm.cs
291
+*.odx.cs
292
+*.xsd.cs
293
+
294
+### MonoDevelop ###
295
+#User Specific
296
+*.usertasks
297
+
298
+#Mono Project Files
299
+*.resources
300
+test-results/
301
+
302
+### VisualStudio ###
303
+## Ignore Visual Studio temporary files, build results, and
304
+## files generated by popular Visual Studio add-ons.
305
+##
306
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
307
+
308
+# User-specific files
309
+
310
+# User-specific files (MonoDevelop/Xamarin Studio)
311
+
312
+# Build results
313
+
314
+# Visual Studio 2015 cache/options directory
315
+# Uncomment if you have tasks that create the project's static files in wwwroot
316
+#wwwroot/
317
+
318
+# MSTest test Results
319
+
320
+# NUNIT
321
+
322
+# Build Results of an ATL Project
323
+
324
+# .NET Core
325
+
326
+
327
+# Chutzpah Test files
328
+
329
+# Visual C++ cache files
330
+
331
+# Visual Studio profiler
332
+
333
+# TFS 2012 Local Workspace
334
+
335
+# Guidance Automation Toolkit
336
+
337
+# ReSharper is a .NET coding add-in
338
+
339
+# JustCode is a .NET coding add-in
340
+
341
+# TeamCity is a build add-in
342
+
343
+# DotCover is a Code Coverage Tool
344
+
345
+# Visual Studio code coverage results
346
+
347
+# NCrunch
348
+
349
+# MightyMoose
350
+
351
+# Web workbench (sass)
352
+
353
+# Installshield output folder
354
+
355
+# DocProject is a documentation generator add-in
356
+
357
+# Click-Once directory
358
+
359
+# Publish Web Output
360
+# TODO: Comment the next line if you want to checkin your web deploy settings
361
+# but database connection strings (with potential passwords) will be unencrypted
362
+
363
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
364
+# checkin your Azure Web App publish settings, but sensitive information contained
365
+# in these scripts will be unencrypted
366
+
367
+# NuGet Packages
368
+# The packages folder can be ignored because of Package Restore
369
+# except build/, which is used as an MSBuild target.
370
+# Uncomment if necessary however generally it will be regenerated when needed
371
+#!**/packages/repositories.config
372
+# NuGet v3's project.json files produces more ignorable files
373
+
374
+# Microsoft Azure Build Output
375
+
376
+# Microsoft Azure Emulator
377
+
378
+# Windows Store app package directories and files
379
+
380
+# Visual Studio cache files
381
+# files ending in .cache can be ignored
382
+# but keep track of directories ending in .cache
383
+
384
+# Others
385
+
386
+# Since there are multiple workflows, uncomment next line to ignore bower_components
387
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
388
+#bower_components/
389
+
390
+# RIA/Silverlight projects
391
+
392
+# Backup & report files from converting an old project file
393
+# to a newer Visual Studio version. Backup files are not needed,
394
+# because we have git ;-)
395
+
396
+# SQL Server files
397
+
398
+# Business Intelligence projects
399
+
400
+# Microsoft Fakes
401
+
402
+# GhostDoc plugin setting file
403
+
404
+# Node.js Tools for Visual Studio
405
+
406
+# Typescript v1 declaration files
407
+
408
+# Visual Studio 6 build log
409
+
410
+# Visual Studio 6 workspace options file
411
+
412
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
413
+
414
+# Visual Studio LightSwitch build output
415
+
416
+# Paket dependency manager
417
+
418
+# FAKE - F# Make
419
+
420
+# JetBrains Rider
421
+
422
+# CodeRush
423
+
424
+# Python Tools for Visual Studio (PTVS)
425
+
426
+# Cake - Uncomment if you are using it
427
+# tools/**
428
+# !tools/packages.config
429
+
430
+# Telerik's JustMock configuration file
431
+
432
+# BizTalk build output
433
+
434
+# End of https://www.gitignore.io/api/visualstudio,monodevelop,csharp

+ 17
- 0
MorseCodeParser.sln View File

@@ -0,0 +1,17 @@
1
+
2
+Microsoft Visual Studio Solution File, Format Version 12.00
3
+# Visual Studio 2012
4
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MorseCodeParser", "MorseCodeParser\MorseCodeParser.csproj", "{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}"
5
+EndProject
6
+Global
7
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
8
+		Debug|x86 = Debug|x86
9
+		Release|x86 = Release|x86
10
+	EndGlobalSection
11
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
12
+		{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}.Debug|x86.ActiveCfg = Debug|x86
13
+		{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}.Debug|x86.Build.0 = Debug|x86
14
+		{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}.Release|x86.ActiveCfg = Release|x86
15
+		{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}.Release|x86.Build.0 = Release|x86
16
+	EndGlobalSection
17
+EndGlobal

+ 201
- 0
MorseCodeParser/AudioMorseDecoder.cs View File

@@ -0,0 +1,201 @@
1
+using System;
2
+using System.Linq;
3
+using System.Collections.Generic;
4
+
5
+using NAudio.Wave;
6
+using Cairo;
7
+
8
+namespace MorseCodeParser
9
+{
10
+    enum MorseTokenType
11
+    {
12
+        ToneStart,
13
+        ToneEnd
14
+    }
15
+
16
+
17
+    struct MorseToken
18
+	{
19
+		public MorseTokenType Type;
20
+		public int Index;
21
+
22
+		public MorseToken(MorseTokenType inType, int inIndex)
23
+		{
24
+			Type = inType;
25
+			Index = inIndex;
26
+		}
27
+
28
+        public override string ToString()
29
+        {
30
+            return string.Format("[MorseToken {0}\tat {1}]", Type, Index);
31
+        }
32
+	}
33
+
34
+	class MorseTone
35
+	{
36
+		public int Index;
37
+		public int Length;
38
+
39
+		public MorseTone(int inIndex, int inLength)
40
+		{
41
+			Index = inIndex;
42
+			Length = inLength;
43
+		}
44
+
45
+        public override string ToString()
46
+        {
47
+            return string.Format("[MorseTone at {0} of length {1}]", Index, Length);
48
+        }
49
+	}
50
+
51
+    public class AudioMorseDecoder
52
+    {
53
+        private string filename;
54
+
55
+        private ISampleProvider samples;
56
+        private readonly int floatBufferSize = 220500 * 4;
57
+        private readonly int windowSize = 100;
58
+        private readonly int stepSize = 25;
59
+
60
+        private readonly float threshold = 0.8f;
61
+
62
+
63
+
64
+        public AudioMorseDecoder(string inFilename)
65
+        {
66
+            filename = inFilename;
67
+
68
+            AudioFileReader reader = new AudioFileReader(filename);
69
+            samples = reader.ToSampleProvider();
70
+        }
71
+
72
+        private List<MorseToken> analyzeSamples()
73
+        {
74
+            List<MorseToken> result = new List<MorseToken>();
75
+
76
+            int buffersRead = 0;
77
+            float[] rawBuffer = new float[floatBufferSize];
78
+            float[] windowedBuffer = new float[(floatBufferSize - windowSize) / stepSize];
79
+
80
+            int samplesRead;
81
+            while(true)
82
+            {
83
+                samplesRead = samples.Read(rawBuffer, 0, floatBufferSize);
84
+
85
+                for(int i = 0, s = 0; i < samplesRead - windowSize; i += stepSize, s++)
86
+                    windowedBuffer[s] = rawBuffer.Skip(i).Take(windowSize).Max();
87
+
88
+                for(int i = 1; i < windowedBuffer.Length; i++)
89
+                {
90
+                    if(windowedBuffer[i - 1] < threshold && windowedBuffer[i] >= threshold)
91
+                        result.Add(new MorseToken(MorseTokenType.ToneStart, (buffersRead * windowedBuffer.Length) + i));
92
+                    else if(windowedBuffer[i - 1] > threshold && windowedBuffer[i] <= threshold)
93
+                        result.Add(new MorseToken(MorseTokenType.ToneEnd, (buffersRead * windowedBuffer.Length) + i));
94
+                }
95
+
96
+                if(samplesRead < floatBufferSize)
97
+                    break;
98
+
99
+                buffersRead++;
100
+            }
101
+
102
+            return result;
103
+        }
104
+
105
+        public List<string> ExtractWords(bool renderImage = false)
106
+        {
107
+            List<MorseToken> tokens = analyzeSamples();
108
+
109
+            if(renderImage)
110
+                drawFingerprint(tokens);
111
+
112
+            List<MorseTone> tones = new List<MorseTone>();
113
+            for(int i = 0; i < tokens.Count; i += 2)
114
+                tones.Add(new MorseTone(tokens[i].Index, tokens[i + 1].Index - tokens[i].Index));
115
+
116
+            int longestToneLength = tones.Max((MorseTone tone) => tone.Length);
117
+			int shortestToneLength = tones.Min((MorseTone tone) => tone.Length);
118
+			int shortestTonePause = tones.Zip(tones.Skip(1), (a, b) => Tuple.Create(a, b))
119
+				.Min((Tuple<MorseTone, MorseTone> tonePair) =>
120
+					tonePair.Item2.Index - (tonePair.Item1.Index + tonePair.Item1.Length)
121
+				);
122
+			int longestTonePause = tones.Zip(tones.Skip(1), (a, b) => Tuple.Create(a, b))
123
+				.Max((Tuple<MorseTone, MorseTone> tonePair) =>
124
+					tonePair.Item2.Index - (tonePair.Item1.Index + tonePair.Item1.Length)
125
+				);
126
+            int mediumTonePause = shortestTonePause * 3;
127
+
128
+            List<string> resultWords = new List<string>();
129
+            string currentWord = "";
130
+            for(int i = 0; i < tones.Count; i++)
131
+            {
132
+                if(i > 0)
133
+                {
134
+                    int toneSpacing = tones[i].Index - (tones[i - 1].Index + tones[i - 1].Length);
135
+
136
+                    int distanceToShortestGap = Math.Abs(shortestTonePause - toneSpacing);
137
+                    int distanceToMediumGap = Math.Abs(mediumTonePause - toneSpacing);
138
+                    int distanceToLongestGap = Math.Abs(longestTonePause - toneSpacing);
139
+
140
+                    if(distanceToMediumGap < distanceToLongestGap && distanceToMediumGap < distanceToShortestGap)
141
+                    {
142
+                        // It's a letter spacing!
143
+                        currentWord += " ";
144
+                    }
145
+
146
+                    if(distanceToLongestGap < distanceToMediumGap && distanceToLongestGap < distanceToShortestGap)
147
+                    {
148
+                        // It's a word spacing!
149
+                        resultWords.Add(currentWord);
150
+                        currentWord = string.Empty;
151
+                    }
152
+                }
153
+
154
+                if(Math.Abs(longestToneLength - tones[i].Length) < Math.Abs(shortestToneLength - tones[i].Length))
155
+                {
156
+                    // It's a long tone
157
+                    currentWord += "-";
158
+                }
159
+                else
160
+                {
161
+                    // It's a short tone
162
+                    currentWord += ".";
163
+                }
164
+            }
165
+
166
+            // Add the last word decoded to the list
167
+            resultWords.Add(currentWord);
168
+
169
+            return resultWords;
170
+        }
171
+
172
+        private void drawFingerprint(List<MorseToken> tokens)
173
+        {
174
+            int fingerprintWidth = 1200, fingerprintHeight = 100;
175
+            float scaleFactorX = (float)fingerprintWidth / tokens.Last().Index;
176
+            using(ImageSurface image = new ImageSurface(Format.Argb32, fingerprintWidth, fingerprintHeight))
177
+            using(Context context = new Context(image))
178
+            {
179
+                context.Antialias = Antialias.Subpixel;
180
+                context.SetSourceColor(new Color(1, 0.4901, 0.1019, 0.8));
181
+
182
+                for(int i = 0; i < tokens.Count; i += 2)
183
+                {
184
+                    MorseToken startToken = tokens[i];
185
+                    MorseToken endToken = tokens[i + 1];
186
+                    context.NewPath();
187
+                    Rectangle tokenArea = new Rectangle(
188
+                        startToken.Index * scaleFactorX,
189
+                        0,
190
+                        (endToken.Index - startToken.Index) * scaleFactorX,
191
+                        fingerprintHeight
192
+                    );
193
+                    context.Rectangle(tokenArea);
194
+					context.Fill();
195
+                }
196
+
197
+                image.WriteToPng("fingerprint.png");
198
+            }
199
+        }
200
+    }
201
+}

+ 49
- 0
MorseCodeParser/MorseCodeParser.csproj View File

@@ -0,0 +1,49 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+  <PropertyGroup>
4
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
6
+    <ProjectGuid>{431E17FD-CF16-4B9E-B282-D71CFD2B3AE6}</ProjectGuid>
7
+    <OutputType>Exe</OutputType>
8
+    <RootNamespace>MorseCodeParser</RootNamespace>
9
+    <AssemblyName>MorseCodeParser</AssemblyName>
10
+    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
11
+  </PropertyGroup>
12
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
13
+    <DebugSymbols>true</DebugSymbols>
14
+    <DebugType>full</DebugType>
15
+    <Optimize>false</Optimize>
16
+    <OutputPath>bin\Debug</OutputPath>
17
+    <DefineConstants>DEBUG;</DefineConstants>
18
+    <ErrorReport>prompt</ErrorReport>
19
+    <WarningLevel>4</WarningLevel>
20
+    <ExternalConsole>true</ExternalConsole>
21
+    <PlatformTarget>x86</PlatformTarget>
22
+  </PropertyGroup>
23
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
24
+    <Optimize>true</Optimize>
25
+    <OutputPath>bin\Release</OutputPath>
26
+    <ErrorReport>prompt</ErrorReport>
27
+    <WarningLevel>4</WarningLevel>
28
+    <ExternalConsole>true</ExternalConsole>
29
+    <PlatformTarget>x86</PlatformTarget>
30
+  </PropertyGroup>
31
+  <PropertyGroup Condition=" '$(RunConfiguration)' == 'Default' ">
32
+    <StartAction>Project</StartAction>
33
+    <StartArguments>"/home/sbrl/Music/Morse Code 2.wav"</StartArguments>
34
+  </PropertyGroup>
35
+  <ItemGroup>
36
+    <Reference Include="System" />
37
+    <Reference Include="NAudio">
38
+      <HintPath>..\packages\NAudio.1.8.0\lib\net35\NAudio.dll</HintPath>
39
+    </Reference>
40
+    <Reference Include="Mono.Cairo" />
41
+  </ItemGroup>
42
+  <ItemGroup>
43
+    <Compile Include="Program.cs" />
44
+    <Compile Include="Properties\AssemblyInfo.cs" />
45
+    <Compile Include="MorseDecoder.cs" />
46
+    <Compile Include="AudioMorseDecoder.cs" />
47
+  </ItemGroup>
48
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
49
+</Project>

+ 102
- 0
MorseCodeParser/MorseDecoder.cs View File

@@ -0,0 +1,102 @@
1
+using System;
2
+using System.Collections.Generic;
3
+
4
+namespace SBRL.Algorithms.MorseCodeTranslator
5
+{
6
+	/// <summary>
7
+	/// A simple class to translate a morse code string into a normal string.
8
+	/// </summary>
9
+	/// <license>Mozilla Public License version 2.0</license>
10
+	/// <origin></origin>
11
+	/// <author>Starbeamrainbowlabs (https://starbeamrainbowlabs.com/)</author>
12
+	/// <changelog>
13
+	/// v0.1 - 26th May 2017:
14
+	///      - Creation! 😁
15
+	/// </changelog>
16
+	public static class MorseDecoder
17
+    {
18
+        /// <summary>
19
+        /// The morse code lookup table. Use the methods in this class is possible,
20
+        /// rather than accessing this lookup table directly!
21
+        /// </summary>
22
+        public static Dictionary<string, char> morseCodeLookup = new Dictionary<string, char>()
23
+        {
24
+            [".-"] = 'a',
25
+			["-..."] = 'b',
26
+			["-.-."] = 'c',
27
+			["-.."] = 'd',
28
+			["."] = 'e',
29
+			["..-."] = 'f',
30
+			["--."] = 'g',
31
+			["...."] = 'h',
32
+			[".."] = 'i',
33
+			[".---"] = 'j',
34
+			["-.-"] = 'k',
35
+			[".-.."] = 'l',
36
+			["--"] = 'm',
37
+			["-."] = 'n',
38
+			["---"] = 'o',
39
+			[".--."] = 'p',
40
+			["--.-"] = 'q',
41
+			[".-."] = 'r',
42
+			["..."] = 's',
43
+			["-"] = 't',
44
+			["..-"] = 'u',
45
+			["...-"] = 'v',
46
+			[".--"] = 'w',
47
+			["-..-"] = 'x',
48
+			["-.--"] = 'y',
49
+			["--.."] = 'z',
50
+			[".----"] = '1',
51
+			["..---"] = '2',
52
+			["...--"] = '3',
53
+			["....-"] = '4',
54
+			["....."] = '5',
55
+			["-...."] = '6',
56
+			["--..."] = '7',
57
+			["---.."] = '8',
58
+			["----."] = '9',
59
+			["-----"] = '0',
60
+        };
61
+
62
+        /// <summary>
63
+        /// Translates a single letter from morse code.
64
+        /// </summary>
65
+        /// <param name="morseSource">The morse code to translate.</param>
66
+		/// <returns>The translated letter.</returns>
67
+        public static char TranslateLetter(string morseSource)
68
+        {
69
+            return morseCodeLookup[morseSource.Trim()];
70
+        }
71
+
72
+        /// <summary>
73
+        /// Translates a string of space-separated morse code strings from morse code.
74
+        /// </summary>
75
+        /// <param name="morseSource">The morse code to translate.</param>
76
+		/// <returns>The translated word.</returns>
77
+        public static string TranslateWord(string morseSource)
78
+        {
79
+            string result = string.Empty;
80
+
81
+            string[] morseLetters = morseSource.Split(" ".ToCharArray());
82
+
83
+            foreach(string morseLetter in morseLetters)
84
+                result += TranslateLetter(morseLetter);
85
+
86
+            return result;
87
+        }
88
+
89
+        /// <summary>
90
+        /// Translates a list of morse-encoded words.
91
+        /// </summary>
92
+        /// <param name="morseSources">The morse-encoded words to decipher.</param>
93
+		/// <returns>The decoded text.</returns>
94
+        public static string TranslateText(IEnumerable<string> morseSources)
95
+        {
96
+            string result = string.Empty;
97
+            foreach(string morseSource in morseSources)
98
+                result += $"{TranslateWord(morseSource)} ";
99
+            return result.Trim();
100
+        }
101
+    }
102
+}

+ 19
- 0
MorseCodeParser/Program.cs View File

@@ -0,0 +1,19 @@
1
+using System;
2
+using System.Collections.Generic;
3
+
4
+using SBRL.Algorithms.MorseCodeTranslator;
5
+
6
+namespace MorseCodeParser
7
+{
8
+    class MainClass
9
+    {
10
+        public static void Main(string[] args)
11
+        {
12
+            AudioMorseDecoder decoder = new AudioMorseDecoder(args[0]);
13
+            List<string> morseWords = decoder.ExtractWords(true);
14
+            Console.WriteLine("Decoded morse code:");
15
+            Console.WriteLine(string.Join("\n", morseWords));
16
+            Console.WriteLine("Deciphered text: {0}", MorseDecoder.TranslateText(morseWords));
17
+        }
18
+    }
19
+}

+ 26
- 0
MorseCodeParser/Properties/AssemblyInfo.cs View File

@@ -0,0 +1,26 @@
1
+using System.Reflection;
2
+using System.Runtime.CompilerServices;
3
+
4
+// Information about this assembly is defined by the following attributes. 
5
+// Change them to the values specific to your project.
6
+
7
+[assembly: AssemblyTitle("MorseCodeParser")]
8
+[assembly: AssemblyDescription("")]
9
+[assembly: AssemblyConfiguration("")]
10
+[assembly: AssemblyCompany("")]
11
+[assembly: AssemblyProduct("")]
12
+[assembly: AssemblyCopyright("")]
13
+[assembly: AssemblyTrademark("")]
14
+[assembly: AssemblyCulture("")]
15
+
16
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
18
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
19
+
20
+[assembly: AssemblyVersion("1.0.*")]
21
+
22
+// The following attributes are used to specify the signing key for the assembly, 
23
+// if desired. See the Mono documentation for more information about signing.
24
+
25
+//[assembly: AssemblyDelaySign(false)]
26
+//[assembly: AssemblyKeyFile("")]

+ 4
- 0
MorseCodeParser/packages.config View File

@@ -0,0 +1,4 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<packages>
3
+  <package id="NAudio" version="1.8.0" targetFramework="net45" />
4
+</packages>

Loading…
Cancel
Save