tgraupmann

Member
  • Content count

    561
  • Joined

  • Last visited

Community Reputation

112 Neutral

About tgraupmann

  • Rank
    Advanced Member
  1. Can you help me plot out a long-term plan?

    Here's a tip.   Some years ago, Torque3D made the mistake of ditching OpenGL for DirectX. This resulted in future stupicide because with a cross-platform engine it prevented porting to Linux, Mac, Android, and iOS. They made some attempts to correct their mistake, but it was too late. There's been a KS attempt, but interest failed.   You might as well take the route of Unity and make it easy on yourself.
  2. Gravi is an intense puzzle-platformer that'll test your tolerance for pain. Fling yourself through terrorizing traps and manipulate gravity to swing towards victory. Death is guaranteed. Please check out our Create Contest Entry and vote for us - http://forums.ouya.tv/discussion/557/gravi-ouya-create-contest-submission#latest [video]http://www.youtube.com/watch?v=qQwjR-aL7TI[/video] APK download is available. Play now!
  3. Unity Ecosystem Generator

    [html]<img height="150" src="http://tagenigma.com/a/ecosystemgenerator/2011-08-28%2C%20Ecosystem%20Generator%20Android%20014.png"/>[/html] Here you can see how to publish to Android and get the Ecosystem Generator working on your phone: [media]http://www.youtube.com/watch?v=PuV6OkCzm6E[/media]
  4. Unity Paint Video Series

    Just letting you know that Unity 3.4 just shipped! [url="http://unity3d.com/unity/whats-new/unity-3.4"]http://unity3d.com/unity/whats-new/unity-3.4[/url] And the Video Painting Series is compatible with 3.4.
  5. Unity 3.4 is right around the corner, and the Paint Video Series is a great way to learn how to use the free version of Unity. You'll learn how to create art for unity. You'll learn how to use the IDE. And then you'll learn how to write script and tie it all together. [url]http://www.youtube.com/watch?v=JiYYp34l-Bw[/url] The video series contains an hour of video footage showing you by example. Go and download the free copy of Unity 3.3 or better. [url]http://unity3d.com/unity/download/[/url] And then head over to the Unity Asset Store and drop $5 for you and all your programming buddies. [url]http://u3d.as/1Dw[/url]
  6. I created a treeview control for Unity that works in the game view, scene view, custom panels and inspectors. You can add items at design time. And you can animate the hover states. It's completely skinable. Feature Video 1: [media]http://www.youtube.com/watch?v=wtcb5U8krdQ[/media] Feature Video 2: [media]http://www.youtube.com/watch?v=p1Jipt_HvH0[/media] Asset Store Link: [url="http://u3d.as/1Uw"]http://u3d.as/1Uw[/url]
  7. Unity Ecosystem Generator

    I've added support to import your own foliage items. Youtube: [media]http://www.youtube.com/watch?v=NPyG6QzDt08[/media] Vimeo: [media]http://vimeo.com/26701662[/media] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot3_thumb.jpg[/img]
  8. My friend Kenny and I put together a package for Unity to auto generate foliage easily on a mesh from within Unity. [media]http://www.youtube.com/watch?v=eeH59UEgef0[/media] The Modo Vimeo user group came out, so I recorded a video of making a mesh in Modo, importing that to Unity, and then throwing some foliage on to that. [media]http://vimeo.com/25795617[/media] Here's some renders of the example scene in the PRO version of Unity. The unity pro version supports camera effects. The Ecosysem Generator works in the free version of Unity without the cool camera effects. We plan on adding many more types of foliage. An undocumented feature is that you can paint foliage on a mask. I'm trying to work that into an editor script so that it works without having to "play" the scene. The Unity extension is available in the Unity asset store. [url="http://u3d.as/1Y1"]http://u3d.as/1Y1[/url] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot1.jpg[/img] [img]http://tagenigma.com/unity/Ecosystem%20Generator/shot2.jpg[/img]
  9. I have a tax question that applies for game programmers. If a Washington, USA resident works as an independent contractor for a company not based in the USA, why is the federal government entitled to tax the individual? I'm sure independent contractors are plentiful. Let's say you are a USA resident, and you work for a USA company then you get taxed. That's how it works. But what if you are a USA resident, you move to a foreign country, you work for a foreign country. Should you be taxed by the foreign country or the USA? And my original question, you are a USA resident, you live in the USA, you work for a foreign country. Should you pay federal taxes? And by work, I mean providing a service. And that service is writing software. Ideas, Thoughts!? Thanks, ~Tim
  10. I added the fade in and fade out... and the popping is gone. I used a 0.15 second fade that seems to do the trick. When the fade starts, I switch to the next channel to play the next sample. using Emotiv; using SlimDX; using SlimDX.XAudio2; using SlimDX.Multimedia; using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Reflection; using System.Runtime.InteropServices; namespace EEG_Example_1 { class EEG_Logger { EmoEngine engine; // Access to the EDK is viaa the EmoEngine int userID = -1; // userID is used to uniquely identify a user's headset /// <summary> /// A dictionary of EEG data by channel /// </summary> Dictionary<EdkDll.EE_DataChannel_t, List<double>> m_eData = new Dictionary<EdkDll.EE_DataChannel_t, List<double>>(); /// <summary> /// The sound thread /// </summary> Thread m_soundThread = null; /// <summary> /// Constructor /// </summary> EEG_Logger() { // create the engine engine = EmoEngine.Instance; engine.UserAdded += new EmoEngine.UserAddedEventHandler(engine_UserAdded_Event); // connect to Emoengine. engine.Connect(); //engine.RemoteConnect("127.0.0.1", 1726); } void engine_UserAdded_Event(object sender, EmoEngineEventArgs e) { Console.WriteLine("User Added Event has occured"); // record the user userID = (int)e.userId; // enable data aquisition for this user. engine.DataAcquisitionEnable((uint)userID, true); // ask for up to 1 second of buffered data engine.EE_DataSetBufferSizeInSec(1); } static void Main(string[] args) { Console.WriteLine("EEG Data Reader Example"); //epoc EEG_Logger p = new EEG_Logger(); //epoc p.Run(); } void Run() { //start the sound thread ThreadStart soundThreadStart = new ThreadStart(WorkerSound); m_soundThread = new Thread(soundThreadStart); m_soundThread.Start(); while (true) { // Handle any waiting events engine.ProcessEvents(); // If the user has not yet connected, do not proceed if ((int)userID == -1) { Console.Error.WriteLine("User is not connected"); return; } Dictionary<EdkDll.EE_DataChannel_t, double[]> data = engine.GetData((uint)userID); if (data == null) { continue; } int bufferSize = data[EdkDll.EE_DataChannel_t.TIMESTAMP].Length; //fill with new data from raw eeg channels for (EdkDll.EE_DataChannel_t channel = EdkDll.EE_DataChannel_t.AF3; channel <= EdkDll.EE_DataChannel_t.AF4; ++channel) { List<double> rawData; if (!m_eData.ContainsKey(channel)) { m_eData.Add(channel, new List<double>()); } rawData = m_eData[channel]; for (int i = 0; i < bufferSize; i++) { double sample = data[channel][i]; rawData.Add(sample); } } Thread.Sleep(0); } } struct SoundItem { public AudioBuffer m_audioBuffer; public DataStream m_dataStream; public SourceVoice m_sourceVoice; public byte[] m_waveData; } // worker for the sound thread public void WorkerSound() { //random Random rand = new Random(); //simdx double SAMPLE_SECONDS = 0.5; //slimdx - create a device XAudio2 device = new XAudio2(); MasteringVoice masteringVoice = new MasteringVoice(device); //slimdx - create a sound format WaveFormat format = new WaveFormat(); format.AverageBytesPerSecond = 88200; format.BlockAlignment = 2; format.Channels = 1; format.SamplesPerSecond = 44100; format.BitsPerSample = 16; format.FormatTag = WaveFormatTag.Pcm; long cbWaveSize = (long)(SAMPLE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx double FADE_SECONDS = 0.15; //slimdx long fadeSize = (long)(FADE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx - fill with data - 88 piano keys List<double> freqtable = new List<double>() { 4186.01, 3951.07, 3729.31, 3520, 3322.44, 3135.96, 2959.96, 2793.83, 2637.02, 2489.02, 2349.32, 2217.46, 2093, 1975.53, 1864.66, 1760, 1661.22, 1567.98, 1479.98, 1396.91, 1318.51, 1244.51, 1174.66, 1108.73, 1046.5, 987.77, 932.33, 880, 830.61, 783.99, 739.99, 698.46, 659.26, 622.25, 587.33, 554.37, 523.25, 493.88, 466.16, 440, 415.31, 392, 369.99, 349.23, 329.63, 311.13, 293.67, 277.18, 261.63, 246.94, 233.08, 220, 207.65, 196, 185, 174.61, 164.81, 155.56, 146.83, 138.59, 130.81, 123.47, 116.54, 110, 103.83, 98, 92.5, 87.31, 82.41, 77.78, 73.42, 69.3, 65.41, 61.74, 58.27, 55, 51.91, 49, 46.25, 43.65, 41.2, 38.89, 36.71, 34.65, 32.7, 30.87, 29.14, 27.5 }; freqtable.Reverse(); //slimdx - make a sound buffer SoundItem[] sounds = new SoundItem[2]; sounds[0].m_audioBuffer = new AudioBuffer(); sounds[1].m_audioBuffer = new AudioBuffer(); //slimdb - set the buffer flags sounds[0].m_audioBuffer.Flags = BufferFlags.EndOfStream; sounds[1].m_audioBuffer.Flags = BufferFlags.EndOfStream; //slimdx - play the sound buffer sounds[0].m_sourceVoice = new SourceVoice(device, format); sounds[1].m_sourceVoice = new SourceVoice(device, format); //time to next buffer DateTime bufferTimer = DateTime.MinValue; //slimdx - cycle buffers int dsIndex = 0; int dsCount = 2; //simdx - Create the sample data into memory sounds[0].m_waveData = new byte[cbWaveSize]; sounds[1].m_waveData = new byte[cbWaveSize]; using (sounds[0].m_dataStream = new DataStream(sounds[0].m_waveData, true, true)) { using (sounds[1].m_dataStream = new DataStream(sounds[1].m_waveData, true, true)) { while (true) { if (sounds[dsIndex].m_sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(0); continue; } //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS - FADE_SECONDS); //slimdx - stop sounds[dsIndex].m_sourceVoice.Stop(); //slimdx -- get buffer byte[] waveData = sounds[dsIndex].m_waveData; //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data //GenerateTone(64, fadeSize, freqtable[41], device, waveData, format); //test GenerateTone(64, fadeSize, freqtable[rand.Next()%freqtable.Count], device, waveData, format); //test //slimdx - start sounds[dsIndex].m_dataStream.Position = 0; sounds[dsIndex].m_audioBuffer.AudioData = sounds[dsIndex].m_dataStream; sounds[dsIndex].m_audioBuffer.AudioBytes = (int)sounds[dsIndex].m_dataStream.Length; sounds[dsIndex].m_sourceVoice.SubmitSourceBuffer(sounds[dsIndex].m_audioBuffer); sounds[dsIndex].m_sourceVoice.Start(); dsIndex = (dsIndex + 1) % dsCount; } Thread.Sleep(0); } } } //slimdx - cleanup the voice sounds[0].m_audioBuffer.Dispose(); sounds[1].m_audioBuffer.Dispose(); sounds[0].m_sourceVoice.Dispose(); sounds[1].m_sourceVoice.Dispose(); //slimdx - dispose the device masteringVoice.Dispose(); device.Dispose(); } // generate some random tones static void GenerateTone(double volume, double fadeSize, double frequency, XAudio2 device, byte[] waveData, WaveFormat format) { double sampleSize = (format.SamplesPerSecond * format.Channels); double t = (Math.PI) / sampleSize; for (long i = 0; (i+1) < waveData.Length; i += 2) { double newVolume; double fade = fadeSize; if (i < fade) { // fade in newVolume = volume * Math.Min(1, i / fade); } else if (i > (waveData.Length - fade)) { // fade out newVolume = volume * Math.Min(1, (waveData.Length - i) / fade); } else { newVolume = volume; } double theta = (double)(i * t * frequency); float amplitude = (int)(Math.Sin((float)theta) * newVolume); // read existing tone - two bytes to float float oldAmplitude = (float)((waveData[i] << 8) | ((int)(waveData[i + 1]))); amplitude = (amplitude + oldAmplitude) * 0.5f; // convert new tone - float to two bytes int data = (int)amplitude; waveData[i] = (byte)(data >> 8); waveData[i + 1] = (byte)data; } } } } [Edited by - tgraupmann on September 19, 2010 9:03:34 AM]
  11. Same result with DataStream. It keeps sputtering between switching buffers. // worker for the sound thread public void WorkerSound() { //random Random rand = new Random(); //simdx double SAMPLE_SECONDS = 0.1; //slimdx - create a device XAudio2 device = new XAudio2(); MasteringVoice masteringVoice = new MasteringVoice(device); //slimdx - create a sound format WaveFormat format = new WaveFormat(); format.AverageBytesPerSecond = 88200; format.BlockAlignment = 2; format.Channels = 1; format.SamplesPerSecond = 44100; format.BitsPerSample = 16; format.FormatTag = WaveFormatTag.Pcm; long cbWaveSize = (long)(SAMPLE_SECONDS * format.SamplesPerSecond * format.BitsPerSample / 8); //slimdx - fill with data - 88 piano keys List<double> freqtable = new List<double>() { 4186.01, 3951.07, 3729.31, 3520, 3322.44, 3135.96, 2959.96, 2793.83, 2637.02, 2489.02, 2349.32, 2217.46, 2093, 1975.53, 1864.66, 1760, 1661.22, 1567.98, 1479.98, 1396.91, 1318.51, 1244.51, 1174.66, 1108.73, 1046.5, 987.77, 932.33, 880, 830.61, 783.99, 739.99, 698.46, 659.26, 622.25, 587.33, 554.37, 523.25, 493.88, 466.16, 440, 415.31, 392, 369.99, 349.23, 329.63, 311.13, 293.67, 277.18, 261.63, 246.94, 233.08, 220, 207.65, 196, 185, 174.61, 164.81, 155.56, 146.83, 138.59, 130.81, 123.47, 116.54, 110, 103.83, 98, 92.5, 87.31, 82.41, 77.78, 73.42, 69.3, 65.41, 61.74, 58.27, 55, 51.91, 49, 46.25, 43.65, 41.2, 38.89, 36.71, 34.65, 32.7, 30.87, 29.14, 27.5 }; freqtable.Reverse(); //slimdx - make a sound buffer AudioBuffer buffer = new AudioBuffer(); buffer.Flags = BufferFlags.EndOfStream; //slimdx - play the sound buffer SourceVoice sourceVoice = new SourceVoice(device, format); //time to next buffer DateTime bufferTimer = DateTime.MinValue; //time to next log DateTime logTimer = DateTime.MinValue; //slimdx - cycle buffers int dsIndex = 0; int dsCount = 2; byte[][] waveDatas = new byte[dsCount][]; //simdx - Create the sample data into memory waveDatas[0] = new byte[cbWaveSize]; waveDatas[1] = new byte[cbWaveSize]; using (DataStream ds0 = new DataStream(waveDatas[0], true, true)) { using (DataStream ds1 = new DataStream(waveDatas[1], true, true)) { DataStream[] streams = new DataStream[dsCount]; streams[0] = ds0; streams[1] = ds1; while (true) { if (sourceVoice.State.BuffersQueued > 0) { Thread.Sleep(0); continue; } //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS); //slimdx - stop sourceVoice.Stop(); //slimdx -- get buffer byte[] waveData = waveDatas[dsIndex]; //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data GenerateTone(freqtable[41], 8, device, waveData, format); //test //GenerateTone(freqtable[rand.Next()%freqtable.Length], 8, device, waveData, format); //test //slimdx - start streams[dsIndex].Position = 0; buffer.AudioData = streams[dsIndex]; buffer.AudioBytes = (int)streams[dsIndex].Length; sourceVoice.SubmitSourceBuffer(buffer); sourceVoice.Start(); dsIndex = (dsIndex + 1) % dsCount; } Thread.Sleep(0); } } } //slimdx - cleanup the voice buffer.Dispose(); sourceVoice.Dispose(); //slimdx - dispose the device masteringVoice.Dispose(); device.Dispose(); }
  12. I'm going to try a SlimDX.DataStream. [example] I had a suspicion it was copying the buffer. Since modifying the buffer while playing did nothing.
  13. I'm providing wave data via a memory stream. And then I pass the memory stream to SlimDX. I want to start and stop the SourceVoice every 50 to 500ms. But when I do I hear popping. Is there a way to start and stop without the popping? //slimdx - fill with more data when the sounds stops if (bufferTimer < DateTime.Now) { bufferTimer = DateTime.Now + TimeSpan.FromSeconds(SAMPLE_SECONDS); //slimdx - stop sourceVoice.Stop(); //slimdx - clear old data for (long i = 0; i < waveData.Length; ++i) { waveData[i] = 0; } // examine the last N seconds of data GenerateTone(freqtable[41], 8, device, waveData, format); //test //slimdx - start ms.Position = 0; buffer.AudioData = ms; buffer.AudioBytes = (int)ms.Length; sourceVoice.SubmitSourceBuffer(buffer); sourceVoice.Start(); } When I generate a tone of 100ms or 2 seconds, when the SourceVoice starts I hear a pop. My issue is within WorkerSound(). [Full source] [Edited by - tgraupmann on September 20, 2010 1:28:53 AM]
  14. [SlimDX] is a pretty neat wrapper around XAUDIO2. DirectX SDK now bundles XAudio2 with C++ examples. I first wrote a tone generator in C++. And with SlimDX it was very easy to port the example over to C#. I spent my weekend on messing with the PCM format, bits, and research. Hopefully you can benefit. [Example] extended. Also I think I heard a bug in Audacity which I used as a reference to listen to tones. I think they blend and multiple with 0.75 instead of 0.5. [This post] talking about the pcm channel bits was helpful too.
  15. [4e6] 4 elements

    What are the 4 elements this year?