Code Projects

Unity3D Refraction Transparency Z-buffering Ghosting Issue

I’m posting this just to supply an image to the Unity3d forums of the issue when using refraction shaders with transparent materials. The refraction process in this scene is to mimic underwater FX. However it seems to apply the effect before getting to the transparency Z-buffer part, because I guess transparent objects need to be done last? Anyhow, it causes the transparent objects to ghost, or be shown offset from what they should be as the refraction shifts the objects to a new location but not if it is transparent. This seems to be a common issue with any refraction based shader as I have tried a few and they all do the same thing.

So my solution is to turn off the refraction setting in the underwater system and apply flag style distortion script to the main camera, which gets it looking pretty close to the refraction method but without the transparency ghosting issue.

Under The Sea Daze

Of course I never live up to my New Year Resolutions and haven’t contributed to this blog in a while. I just get too damned wrapped up in my projects and stuff going on. I also easily get sidetracked into other projects. Like this one, a visual screen saver concept that is to go with the new Junior Desktop for children friendly Kiosk systems. This is a personal journal entry in my blog to go over the project, what it is about, my goals and solutions.

Building on the framework for the Windows Screen Savers which supports multi-monitor configurations. This image above shows a panorama view of the program spanning across 3 displays.

I had made lots of screen savers in 2017, I basically spent that entire year tweaking the engine and coming up with new concepts for screen savers to add to my site WindowsScreenSavers.com. It had always been a goal, since I started that project, to make an aquarium version. I will admit that it isn’t as visually beautiful as some of the others, nor does it really compete with the video versions of similar aquatic screen savers, but what it does have is character.

Every day there is something new to be witnessed in this program. Special holidays included, like Christmas, Easter, Halloween, and Columbus Day. Not just those major holidays but obscure ones I didn’t even know existed until I began researching this project. Such as Popcorn Day, the Ides of March, Submarine Day, Goth Day, Kite Day, Ask a Stupid Question Day. The list was daunting, but I have finally closed in to near to handful of the last ones and the end is in sight.

A lot of the assets I had or were easily obtained through Unit’s Asset store or places like TurboSquid. However as I added more assets to the project the file size grew, and grew and when it peaked 1.5 Gigs I knew I needed to reign this madness in. Using tools like Rhino 3D I decimated the meshes taking some like the bust of George Washington from over a 300,000 vertices down to 52,000 (and I could probably crunch that more with little loss of detail.) Then I had to crunch the texture maps, because there was a ton of them and a high quality map of 2048×2048 usually resulted in eating up over 2.7 MB. When you consider most material texture requires a Color Map, Normal Map and often Occlusion and Metallic map all at 2048×2048 that one material is then eating up 10 MP of space. So crunch crunch crunch down to 256 or 512, or if it is close to the camera and the detail is needed it got to be 1024×1024. I also would ditch the occlusion and often the metallic maps. Eventually I got the entire thing down to just under 450 GB. Not bad, more than 60% reduction in space required and more importantly it will fit on CD-R media disc for easier distribution. Of course there will be a download option too.

I created a lot of the models and fish skins myself using Rhino 3D, Corel Draw and Substance Painter. Yeah I have the Adobe Suite with Photoshop, but my god it just too bulky and clumsy to use unless absolutely needed, and it is sometimes, especially when assets come with textures in PSD format, stop that people…just STOP! Use PNG or TGA!

As this project winds up, my son Nick is bugging me to finish work on another project we had dabbled on while in Breckinridge skiing for a week, The Boom Game. That one I’ll write up another journal on I would imagine. I just hope it doesn’t take as much time as this one did, 3 months so far. I also have my major project the dungeon crawl game which was coming along well and looking amazing when it got put on hold to do this silly thing. Ok it’s not silly, I hope it will help drive the new Kid Computers site. Let’s face it hardware is dead, I have to re-energize that company with software solutions.

That’s about it for now. Hopefully I will post again before 2020. HAHAHAHA.

PHP CVS to MySQL

This PHP program is intended as a heavy duty automated tool for converting CSV (comma separated value) to a MySQL import file or querying it directly into a MySQL database. It can be used simply with a single static method call or with more flexibility and power by creating it as an object.

Download this CVS to MySQL from github.

It is not so trivial as one may first think to convert data from one format to another. To truly take advantage of MySQL querying of data in useful ways the data must be properly assigned a data type, such as INT, FLOAT, VARCHAR, TEXT, TIME and so on. The method implemented in this script to do this is REGEX. The regex pattern matching is leveraged to pigeon hole the data into the most appropriate type for MySQL to use. Every data entry must be scanned to detect if it is a certain type of data, a data type that maybe only integer numbers would of course become an INT type, but if even one of ten thousand entries has a decimal in it, then the entire set must become a float, double or numeric.

An INT simply converted to a VARCHAR is not very useful when trying to query data that should be an integer. The default regex rules file is “regex_mysql_data.txt” and has comment lines in it that start with the # character. You may want to go about modifying this file to fit your needs or to improve upon the matching capabilities.

Besides regex pattern matching, the data string length is also considered. This is done first to determine if that data should even be considered being compared to the regex pattern type. This is most useful for text based data to determine if it should be of types VARCHAR, TEXT, MEDIUMTEXT, LONGTEXT
Here is a simple static example to create a CSV to MySQL import.

CSVtoMySQL::ToHTML('test.csv');

All the static methods assume there is a header as the first row of the CSV file. This static method will try to detect a primary key, if it cannot determine a suitable primary key it will assign an INT at the beginning named ‘id’.

If you do not want to rely upon the auto detection of a primary key use this example:

CSVtoMySQL::ToHTMLMyKey ('test.csv', ‘MyID’);

Where “MyID” (optional) will become the name of the new primary key and no auto detection will be attempted.

-= THE STATIC METHODS =-

ToString – These static methods will display no output but only return the results as a string.

$string = CSVtoMySQL::ToString( $in_file [,$delim = ‘,’] )
$string = CSVtoMySQL::ToStringMyKey( $in_file [,$my_key = ‘id’ [,$delim = ‘,’]] )

ToFile – These methods will send the information to a file supplied as $out_file.
Null = CSVtoMySQL::ToFile( $in_file, $out_file, [$delim = ‘,’] )
Null = CSVtoMySQL::ToFileMyKey( $in_file, $out_file [,$my_key = ‘id’, [$delim = ‘,’]] )

ToScreen – These methods will print the mysql import information directly to the screen.

Null = CSVtoMySQL::ToScreen( $in_file [,$delim = ‘,’] )
Null = CSVtoMySQL::ToScreenMyKey( $in_file [,$my_key = ‘id’ [,$delim = ‘,’]] )

ToHTML – Like ToScreen methods but they will also add the HTML line break tag where the new line is.

Null = CSVtoMySQL::ToHTML( $in_file [,$delim = ‘,’] )
Null = CSVtoMySQL::ToHTMLMyKey( $in_file [,$my_key = ‘id’ [,$delim = ‘,’]] )

ToMySQL – These methods will use your mysql connection to send the mysql query directly to the database. You must have already connected to the mysql server and database before calling either of these methods.

Null = CSVtoMySQL::ToMySQL( $in_file [,$delim = ‘,’] )
Null = CSVtoMySQL::ToMySQLMyKey( $in_file [,$my_key = ‘id’ [,$delim = ‘,’]] )

-= CLASS USAGE =-

Creating a class object is more powerful then the static methods as there a lot of helper methods for fine tuning and debugging.

To create as an object:

$c2m = new CSVtoMySQL('test.csv');

//Then you can do something like:
$c2m->add_blank_tag('NA');
$c2m->add_blank_tag('M','PHONE');
$c2m->set_mysql_file(‘mymysql.sql’);
$c2m->detect_primary_key();
$c2m->to_file();

Here is another example where you export the CSV file and import directly to the mysql database.


<?php

require_once('CSVtoMySQL.php');

$sql = mysql_connect('xxx.xxx.xxx.xxx', 'user', 'password');
mysql_select_db('database',$sql);

$c2m = new CSVtoMySQL('test.csv');
$c2n->set_table_name(‘mytable’);
If($c2m->detect_primary_key() == false)
	{
	$c2m->add_primary_key(‘id’);
}
$c2m->to_mysql();

-= CLASS METHODS =-

The constructor:
__construct($csv, [$mysql = “mysql.sql” [,$hashead = true]])

This method loads the regex file and can be load a custom regex file.
Null = load_regex($regex_file = ”)

Reserved words are words that conflict with mysql syntax statements, such as VARCAR, INSERT, UPDATE, DATASE to prevent conflicts a rule file named “reserved_mysql_words.txt” is loaded and used to compare against the CSV header names. Any matches are renamed to prevent conflicts. You can override this file with your own using this method.
Null =load_reserved_words($f = ”)

Method to set the CSV file
Null = set_csv_file($file)

Method to set the path and name of the mysql output file, but only needed if actually creating an out file.
Null = set_mysql_file($file)

By default the CSV delimiter (data separator character) is comma “,” but there is an auto detect pass that will try and match with other common delimiters (such as |,tabs, spaces). If you need to set this manually use this method.
Null = set_delimiter($v)

Use this method to set the mysql table name, by default the table name is the name of the CSV file itself minus the extension.
Null = set_table_name($s)

When reading in CSV file line by line, the max length of each line is set to 0, which in PHP 5.1+ is unlimited to end of line. However, if you need to set this to a specific length use this method.
Null = set_max_line_length($v)

This method allows you to insert a new field that does not exist in the CSV file. $v is the name of the field, and the optional secondary value is the type which is defaulted to VARCHAR(255)
Null = add_field($v [,$type = ‘VARCHAR(255)’])

This method allows you to change the field name based on $n which can be an index number or name and $name is the new name to be given.
Bool = change_field_name($n,$name])

Use this method to set the primary key index. If $v is a number then the key is the field index, if a name it is matched against the header field name.
Bool = primary_key($v)

Like above method but only applies to the field name, not the index
Bool = primary_key_col_by_name($s)

Like above but only applies to setting the primary key by index, where the first field index = 0, not 1!
Bool = primary_key_col_by_number($n)

Add your own custom primary key with this method. This should be an INT as it will also be set to auto increment. Set the starting point of the auto increment public variable $user_primary_key_inc [ = 0]
Null = add_primary_key ([$name = ‘id’ [,$type = ‘INT’ [,$start_at = -1]]])

This method is used to try and detect which field in the CSV file should be used as the primary key. It begins with the first column and tries to match any INT or VARCHAR type that is all unique and contains no empty records. As soon as it finds one it sets that as the primary key. Also see notes in the “regex_mysql_data.txt” file. If $n is supplied it can either be a number which matches the index of the CSV column (where first column is 0, not 1) or the name of the actual column. This method retruns true if it was able to match a primary key, and false if it failed.
Bool = detect_primary_key($n = ”)

A helper method to test the types of fields detected
Null = print_types()

Same as above but outputs as HTML
Null = print_html_types()

The method to call for returning the results as a string.
String = to_string()

Send the output to the screen. I use it for when I am working in telnet or ssh
Null = to_screen()

Send the output like the to_screen() method but includes html breaks at the new line locations.
Null = to_html()

This method writes the output to a file, if you hadn’t already set the output file name you can supply it.
Bool = to_file([$file = ”])

This method sends the parsed CSV file directly to the MySQL database, you must have a connection already established (see usage above for an example.)
Bool = to_mysql()

Adds a blank tag identifier to the blank_tags array. Sometimes data will be in a CSV file that should be treated as if it were blank, such as with ‘NA’, ‘-‘, or the like. You can add global tag blanks with this method that cause this type of data to be ignored or treated as if it were empty. You can set the column field name here which apply the blank tag to just a specific column otherwise if blank it is treated globally against all columns.
Null = add_blank_tag($v [,$col = ”])

This method is ran automatically by several functions, but if you need to call it yourself you can. This method will attempt to determine the data type a column is using the “regex_mysql_data.txt” file and its rules.
Null = detect_types()

Used to try and detect if the CVS file contains a header. This is very problematic and not 100% accurate. By default the public variable $detect_header = false and must be set to true for this method to work. Otherwise it assumed there is a header. The method returns true if it detected a header and false if it did not.
Bool = detect_header($s)

-= ADDITIONAL CLASS HELPERS =-

CSVtoMySQL_DetectType is a class that is created and stored in the $regex_match_file array that contains the information from the “regex_mysql_data.txt” file.

CSVtoMySQL_FieldType is a class that is created and stored in the $fields array and contains information regard each CSV column and it’s fields.

Text to Speech with PHP (TTS)

elephanttalk

A really quick and easy Text to Speech class for PHP that will generate an MP3 file. You can also easily setup an Ajax call on a website to play the text to speech audio file as you generate it. The quality is pretty good compared to other solutions but I haven’t figured out how to adjust pitch and tone or mix background music with it (yet.)

This is not really a solid solution for robust TTS as it relies on Google’s TTS API service; for more advanced solutions with lots of controls and embedding into videos we use Microsoft’s TTS system. But for easy to deploy and on demand web services this solution is a synch.

This Text to Speech with PHP version can be found on my CodeSlinger GitHub page.

<?php
/******************************************************************
Projectname:   PHP Text 2 Speech Class 
Version:       1.0 
Author:        Radovan Janjic <rade@it-radionica.com> 
Last modified: 11 06 2013 
Copyright (C): 2012 IT-radionica.com, All Rights Reserved 

* GNU General Public License (Version 2, June 1991) 
* 
* This program is free software; you can redistribute 
* it and/or modify it under the terms of the GNU
* General Public License as published by the Free
* Software Foundation; either version 2 of the License, 
* or (at your option) any later version.
* 
* This program is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the 
* implied warranty of MERCHANTABILITY or FITNESS FOR A 
* PARTICULAR PURPOSE. See the GNU General Public License 
* for more details. 

Description: 

PHP Text 2 Speech Class 

This class converts text to speech using Google text to  
speech API to transform text to mp3 file which will be  
downloaded and later used as eg. embed file.  

Example: 

****************************************************************** 
<?php
$t2s = new PHP_Text2Speech; 
?> 

// Simple example 
<audio controls="controls" autoplay="autoplay"> 
  <source src="<?php echo $t2s->speak('If you hear this sount it means that you are using PHP text to speech class.'); ?>" type="audio/mp3" /> 
</audio>

// Example use of other language 
<audio controls="controls" autoplay="autoplay"> 
  <source src="<?php echo $t2s->speak('Wie geht es Ihnen', 'de'); ?>" type="audio/mp3" /> 
</audio> 

******************************************************************/ 

class PHP_Text2Speech { 
     
    /** Max text characters
     * @var    Integer  
     */ 
    var $maxStrLen = 100; 
     
    /** Text len
     * @var    Integer  
     */ 
    var $textLen = 0; 
     
    /** No of words 
     * @var    Integer  
     */ 
    var $wordCount = 0; 
     
    /** Language of text (ISO 639-1) 
     * @var    String  
     * @link https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes 
     */ 
    var $lang = 'en'; 
     
    /** Text to speak 
     * @var    String  
     */ 
    var $text = NULL; 
     
    /** File name format 
     * @var    String  
     */ 
    var $mp3File = "%s.mp3"; 
     
    /** Directory to store audio file
     * @var    String  
     */ 
    var $audioDir = "audio/"; 

    /** Contents 
    * @var    String 
    */ 
    var $contents = NULL; 
     
    /** Function make request to Google translate, download file and returns audio file path 
     * @param     String     $text        - Text to speak 
     * @param     String     $lang         - Language of text (ISO 639-1) 
     * @return     String     - mp3 file path 
     * @link https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
     */ 
    function speak($text, $lang = NULL) { 
         
        if ($lang !== NULL) { 
            $this->lang = $lang; 
        } 

        // Create dir if not exists 
        if (!is_dir($this->audioDir)) { 
            mkdir($this->audioDir, 0755) or die('Could not create audio dir: ' . $this->audioDir); 
        } 
         
        // Try to set writing permissions for audio dir. 
        if (!is_writable($this->audioDir)) {  
            chmod($this->audioDir, 0755) or die('Could not set appropriate permissions for audio dir: ' . $this->audioDir); 
        } 
         
        // Can not handle more than 100 characters so split text 
        if (strlen($text) > $this->maxStrLen) {
            $this->text = $text;

            // Generate unique mp3 file name 
            $file = sprintf($this->mp3File, $this->audioDir . md5($this->text)); 
            if (!file_exists($file)) {
                $texts = array();
                $words = explode(' ', $this->text);
                $i = 0;
                $texts[$i] = NULL;
                foreach ($words as $w) {
                    $w = trim($w);
                    if (strlen($texts[$i] . ' ' . $w) < $this->maxStrLen) {
                        $texts[$i] = $texts[$i] . ' ' . $w;
                        if (preg_match('/[:;,.!?-]$/', $w)) { $i++; } // seperate at common breaks
                    } else {
                        $texts[++$i] = $w;
                    } 
                }

                // Get get separated files contents and marge them into one
                foreach ($texts as $txt) {
                    $pFile = $this->speak($txt, $this->lang); 
                    $this->contents .= $this->stripTags(file_get_contents($pFile)); 
                    unlink($pFile);
                }
                unset($words, $texts); 
                 
                // Save file
                file_put_contents($file, $this->contents); 
                $this->contents = NULL;
            }
        } else {
             
            // Generate unique mp3 file name 
            $file = sprintf($this->mp3File, $this->audioDir . md5($text)); 

            if (!file_exists($file)) { 
                // Text lenght 
                $this->textLen = strlen($text); 
                 
                // Words count 
                $this->wordCount = str_word_count($text); 

                // Encode string 
                $text = urlencode($text);

                // Download new file
                $this->download("http://translate.google.com/translate_tts?ie=UTF-8&q={$text}&tl={$this->lang}&total={$this->wordCount}&idx=0&textlen={$this->textLen}", $file);
            }
        } 
         
        // Returns mp3 file path 
        return $file; 
    } 
     
    /** Function to find the beginning of the mp3 file 
     * @param     String     $contents        - File contents 
     * @return     Integer 
     */  
    function getStart($contents) { 
        for($i=0; $i < strlen($contents); $i++){ 
            if(ord(substr($contents, $i, 1)) == 255){ 
                return $i; 
            } 
        } 
    } 
     
    /** Function to find the end of the mp3 file 
     * @param     String     $contents        - File contents 
     * @return     Integer 
     */  
    function getEnd($contents) { 
        $c = substr($contents, (strlen($contents) - 128)); 
        if(strtoupper(substr($c, 0, 3)) == 'TAG'){ 
            return $c; 
        }else{ 
            return FALSE; 
        } 
    } 

    /** Function to remove the ID3 tags from mp3 files 
     * @param     String     $contents        - File contents
     * @return     String
     */
    function stripTags($contents) {
        // Remove start
        $start = $this->getStart($contents);
        if ($start === FALSE) { 
            return FALSE;
        } else { 
            return substr($contents, $start);
        } 
        // Remove end tag 
        if ($this->getEnd($contents) !== FALSE){ 
            return substr($contents, 0, (strlen($contents) - 129));
        } 
    } 

    /** Function to download and save file 
     * @param     String     $url        - URL 
     * @param     String     $path         - Local path 
     */
    function download($url, $path) {  
        // Is curl installed? 
        if (!function_exists('curl_init')){ // use file get contents  
            $output = file_get_contents($url);
        }else{ // use curl  
            $ch = curl_init();  
            curl_setopt($ch, CURLOPT_URL, $url);  
            curl_setopt($ch, CURLOPT_AUTOREFERER, true);
            curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1");  
            curl_setopt($ch, CURLOPT_HEADER, 0);  
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);
            $output = curl_exec($ch);  
            curl_close($ch);
        } 
        // Save file
        file_put_contents($path, $output);
    }
}

Here is an example of using the TTS class in PHP.

<?php
include 'PHP_Text2Speech.class.php';

$t2s = new PHP_Text2Speech;
?>

<audio controls="controls" autoplay="autoplay">
  <source src="<?php echo $t2s->speak('What are you looking at? Wipe that face off your head.'); ?>" type="audio/mp3" />
</audio>

What is Spinning and a Spin Function (PHP)

dreamstimesmall_2869597

Spinning Basics 101

Spinning generally refers to randomly generating articles, content and data based on option sets. Typically a template or as I call it a “boil plate” is created identify the set. I will address the use of spinning for generating articles and other sentence content but as you will easily derive the content does not need to be limited to just words and sentences, you can spin html, CSS, PHP code, data and more.
Say we have a sentence such as “I love my car.” How else could we say this?

I love my automobile.

I like my car.

I really like my vehicle.

These sentences roughly all portray the same meaning but each is distinctly different. When it comes to unique article generation this technique can be invaluable. All we have to do get all these variations and other combinations is generate a boiler plate for the sentence like so.

I {really |}{love|like} my {car|automobile|vehicle}.

So as you can see above all versions of the sets of words are contained in the curly brackets each version separated by the pipe character (the straight vertical line.) Pipe us used because it one has been a standard data delimiter and two because it also a shortcut for OR in programming logic. There is no so called standardization for spinning but it is widely used.

In our example we can see that when spun the set {love|like} means there is equally likely chance that either word will be chosen and used in this spot. For {really|} we see there is only one word, but there is still a pipe followed by a bracket, this indicates there is a chance that really or “nothing” will be selected. Also the last set contains car, automobile and vehicle all with an equal chance to be chosen.

But say we wanted the word ”love” to have a greater chance then like to be chosen? If each of the two words has a 50/50 chance we can increase the odds for the word like by going {like|love|love} now “love” has 2 in 3 chances or 66% probability of being chosen. Same thing can be applied if we want to reduce the odds of the word “really” we can go {really|||} now we have 3 blank spaces to the one choice for “really” giving the word only a 25% chance of being used.

Nested Spinning

With recursive functions such as the one at the end of this article, you can create boiler plates with nested spins, that is spins within spins.
For example:

Spinning is a {{great|wonderful|good} tool|hot {topic|subject}} for SEO.
When nesting it can start to become confusing to decipher the text but if you break it down like so it is easier to see.

{
	{great|wonderful|good} tool
	|
	hot {topic|subject}}
}

If the first element of the top spin is chosen followed by the second element of the nested spin we get “Spinning is a wonderful tool for SEO.”
Spinning has no restrictions on the levels of nesting you want to add.

Spinning Function for PHP

This has been a very introductory article on the concepts of spinning, most spinning also incorporates deeper elements such as dynamic variables, synonym spinning, adjective and grammar injection and more.

If you are ready to get spinning using some simple PHP code here you go.

function spin($s)
	{
	preg_match('#\{(.+?)\}#is',$s,$m);
	if(empty($m)) return $s;
	$t = $m[1];
	if(strpos($t,'{')!==false)
		{
		$t = substr($t, strrpos($t,'{') + 1);
		}
	$parts = explode("|", $t);
	shuffle($parts);
	$s = preg_replace("+\{".preg_quote($t)."\}+is", $parts[array_rand($parts)], $s, 1);
	return spin($s);
	}

Of course you can create similar functions in almost any language including C++,C#, Perl, Python and so on.

Find All Installed TTS Voices for Microsoft Speech Platform SDK (C#)

 

When working with Text To Speech (TTS) voices such offered in the Microsoft Speech Platform SDK and Server Runtime Languages it is not apparent that the voices are actually installed. These voices are offered in an SDK for developers but are not integrated as part of the systems TTS options as you would expect to find in the control panel, speech properties section.

Here is a quick how to for those wanting to install and use these TTS voices in their own C# project.

Download and install the SpeechPlatformRuntime.msi from here:
http://www.microsoft.com/en-us/download/details.aspx?id=24974

Make sure you install the correct version, x64 or x86.

Download and install language and voice packages you prefer from here:
http://www.microsoft.com/en-us/download/details.aspx?id=3971

Start a new C# console project in Visual Studio Express 2012 or whatever version you prefer and name it “SpeechVoicesCheck”.

Take the Micosoft.Speech.dll file and copy it into your project directory and note its location.

Add as a reference to the project by browsing to where you put Microsoft.Speech.dll and including it. This allows you to now add the in the using section to make use of the platform methods:

using Microsoft.Speech.Synthesis;

Here is the code to for the new project which will list all of your installed voice packages and some information regarding them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Speech.Synthesis;

namespace SpeechVoicesCheck
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer speaker = new SpeechSynthesizer();
            Console.WriteLine("INSTALLED VOICES");
            Console.WriteLine("");

            
            foreach(InstalledVoice voice in speaker.GetInstalledVoices())
            {
                VoiceInfo info = voice.VoiceInfo;
                
                Console.WriteLine("Voice: " + info.Id + " : " + info.Name + " : " + info.Gender + " : " + info.AdditionalInfo);
                Console.WriteLine("");
            }

            Console.WriteLine("");
            Console.WriteLine("Press any key to close...");

            Console.ReadLine();

        }
    }
}

First 10,000 Prime Numbers

Primes, those integers that can only be divided by 1 and themselves. Here is a list of the first ten thousand prime numbers.

Integer Numbers

 

I find numbers extremely fascinating even though I am usually horrible at math I enjoy logical functions and algorithms and especially data structures (probably why I love object orientated languages so much.)  Recently I was playing with some concepts of on demand generated websites that could generate thousands of unique pages utilizing very few lines of code. There are lots of ways to do this, but at the same time I felt one of the goals must be to also generate on those pages some kinds of useful and/or meaningful information.

Within a couple of days I had a little less than thousand lines of code and about 5 web page templates put together to generate every prime number between 1 and 9,223,372,036,854,775,807. That is nine quintillion two hundred twenty-three quadrillion three hundred seventy-two trillion thirty-six billion eight hundred fifty-four million seven hundred seventy-five thousand eight hundred seven.

It’s important because it’s the limiting factor of a 64 bit integer. You’ve probably heard that computer code is really 0’s and 1’s, that’s right. In binary we count using only the digits 0 and 1 instead of 1 through 10 but you add and carry exactly the same.


0001 = 1

0010 = 2

0011 = 3

but when you have 63 of these all set to 1

111111111111111111111111111111111111111111111111111111111111111

it comes out to our magic number of 9,223,372,036,854,775,807.

Why not 64 digits? Because the last bit in PHP is reserved for indicating positive or negative. Some languages such a C allow you to extend the number by sacrificing negative numbers, this is referred to as an “unsigned integer”. But PHP does not support unsigned.

So I put this website together to try and extrapolate interesting information about numbers at IntegerNumber.com, things such as is it a prime number, what divisors and factorization values does it contain, simple hash codes and other base representations besides the standard base 10 and binary.

Just imagine however if Google or another search engine was to try and crawl and index every one of those pages. If Google could crawl 1 page a second, it would take 292,277,506,246 years to crawl every page. That is 20 times the current age of the universe. Also at roughly 1k bits of information per page the storage capacity required would be…my calculator broke…let us say lot 🙂

So to be nice to my hosting provider I decided to limit it to the integer 2,147,483,647 which is max for a 32 bit integer with a length of 31 binary 1’s. Am I not merciful.

 

Quickest Way to Find Prime (PHP)

I had run across a few code snippets of other code slingers discussing algorithms that could run fast enough for real time processing to calculate prime numbers be determining the divisors.  Being the egotistical coder I am I didn’t even bother looking at their code before quickly pulling up my notepad and jotting down a quick for loop to do just that.

The function seemed to work well enough for small integers but at larger numbers in excessive of several million the time to process the loop was excessive.  So then the fun begins, well I find it fun, a puzzle to solve, kind of like solving a Sudoku.  Figure out how to reduce the number of operations to solve the problem.

It is obvious that no divisor is greater than half the number, so (n/2) cuts the operation literally in half. But still larger integers were a taking way too long. So then reading up on some math you can calculate factorizations based on square roots that divide to equal zero. However now we are left with a factorization that looks like this: 2 * 32 * 7 * 11 * 31 * 151 * 331 for the Integer 2147483647 (the highest 32 bit integer in PHP.) Finding the factorization based on the square root of the number is quick and then you simply have to calculate every permutation. A simple sort function gets the work done in O(n^2).

Once you have the number of divisors you only have to count the number to determine if it is prime, which is two, 1 + itself.

 

function primefactor($num)
	{
	$sqrt = sqrt($num);
	for ($i = 2; $i <= $sqrt; $i++)
		{
		if ($num % $i == 0)
			{
			return array_merge(primefactor($num/$i), array($i));
			}
		}
	return array($num);
	}

function divisors($primes,$num)
	{
	$num_primes = count($primes);
	$divisors = Array();

	$limit = pow(2, $num_primes) - 1;

	for($number = 0; $number <= $limit; $number++)
		{
	  $divisor = 1;
		for($i = 0; $i < $num_primes; $i++)
			{
			$divisor *= ($number >> $i) & 1 ? $primes[$i] : 1;
			}
		$divisors[] = $divisor;
		}

	sort($divisors);
	return array_unique($divisors);
	}