• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Monday, 30 Jul 2007 01:58

Here are some shots of my first Gundam model.

Gundam Astray Red Frame gallery

It's a Gundam Astray Red Frame in 1/100 scale. The color scheme calls for a bright red for the frame but I wanted to experiment with something darker so I went for Hull Red which I then went over in Clear Red because it wasn't red enough. The result is a kind of chocolate color and I'm still not sure I like it. Most of the panel lines were done with oil paint and mineral spirits and took a very long time to clean up. Then, right at the end, I tried Copic Multi Liner inking pens which give a great result very quickly. In future I'll use those and/or my Koh-I-Noor Rapidograph pens which I haven't tried yet.

Author: "stevewhitepsfd"
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 29 Apr 2007 06:12

Kit

I bought the kit for about $13 from the local HobbyTown USA store in Redmond Town Center early in 2007. Prior to that, it must have been nearly thirty years since I'd bought and built a plastic scale model kit and that would have almost certainly been an Airfix one too, probably from a model shop in Wakefield, Yorkshire . Most of the kits in the Redmond store are by Tamiya, Dragon, Hasegawa, Revell, Italeri and Bandai so I was surprised when I saw this kit and was reminded of the familiar brand from my youth. The kit isn't particularly well detailed compared to, say, the Hasegawa Hurricane Mk II kit. But the Hasegawa is nearly twice as expensive.

As a kid, my kit builds were a mess. I'd get polystyrene cement smeared on surfaces and canopies, there'd be gaps in the seams, I wouldn't be surprised if once or twice I slapped my decals on first and then tried to paint around them! Building and painting were always fun, but rushed, processes. Now I've finished my first model as an adult and I see that the polystyrene pieces in the box provide a canvas (a three-dimensional one: in some ways as blank and daunting as a real canvas, in other ways as simple as painting-by-numbers) that challenges the modeler to dress it up in the illusion of a real painted, dirtied and worn 1:1 scale object.

Build

I first washed the sprues with dish soap, rinsed and dried them. I used a Squadron sprue nipper to remove the pieces from their sprue. It stayed sharp for this project but it got blunt surprisingly quickly during the next. I tried sharpening it with a Dremel grinding stone but I wasn't happy with the result. So I tried a pair of diagonal cutting pliers which are shown in the photograph. As soon as I felt the effortless and precise action of the pliers, the nippers went straight in the waste basket.

There was a lot of flash on the kit's pieces so I did a lot of scraping (with a craft knife) and sanding during the build. Similarly the fuselage, wings and tail all needed a lot of filling and sanding to smooth out the seams. For filler I used Squadron white putty and a cocktail stick. The pieces were joined with Model Master Liquid Cement For Plastic Models and I used Staples rubber bands to hold the halves of the fuselage together while the cement dried.

Paint

I'd had to paint the cockpit during the build. I gave it a coat of flat black first to act as shadows, then went over that with dark green on a fairly dry brush. Finally I gave it a little shading and character with various shades of Doc O'Brien's weathering powders.

Before proceeding I wiped the model down with Polly S plastic prep and then airbrushed it with white primer. The color scheme I chose was that of No.85(F) squadron, RAF Advance Striking Force, Lille/Seclin, France, April 1940.

I used Tamiya acrylic flat earth and dark green for the upper side camouflage pattern and it took me several attempts probably due to my inexperience with an airbrush. I don't know if it was because I wasn't cleaning it properly or whether I didn't have the paint thickness and air pressure well enough matched but I had several performance problems with the Badger airbrush. The main issue was controlling the color: far too often I'd get either all or nothing out of it, and the needle is prone to sticking in the fully open position. The Paasche airbrush (the red one in the photograph below) hasn't given me any such problems so far and it feels far more smooth, robust and precise in use. In future I'll use the Badger for clear coats and perhaps for primer and the Paashe for controlled painting.

To smooth down my poor paint job I used 400 grade sandpaper which had the unfortunate side effect of taking off some panel lines on the left wing. I also used Tamiya polishing compound on a painter's rag and I think that helped to even out and subdue the gradients between the two colors. The flat black and white underside required some masking in order to get a straight line down the center of the undercarriage. I began by painting the white half.

Despite my masking efforts, some white paint managed to get through creases in the polythene onto the fuselage and tail fin and had to be touched up. I couldn't face masking up again for the black half so I just hand-brushed that with some care. There is, predictably, a world of difference in finish and smoothness between the airbrushed and hand-brushed halves as you can see in the photograph below. More polishing helped but I think I learned my lesson there. As it happens, though, you may not notice any real consequence of my impatience when you see the final photographs at the end.

To seal the paint and prepare the model with a gloss surface for the decals, I applied a generous coat of Future floor finish from the airbrush.

In remorse for my earlier mask-avoidance, I spent some time doing some sterile-drape-looking masking for a little airbrushing on the wing roots. I guess modeling is a little like surgery at times; more evidence of that in the following section.

Repair and customize

According to research I did, the kit had located the hole for the foot stirrup in the wrong place, and the directions show it being mounted perpendicular to the fuselage instead of parallel with it. I filled the existing hole with putty and made a new one with a drill bit in a pin vise. I used the same tool to make a hole in the top of the tail fin to take a small aerial mast which I made from some heat-stretched sprue. For the aerial itself I stretched cotton twine between the two masts and another from the forward mast to the fuselage.

I decided to model the kit with the canopy open so I cut the canopy in two with a razor saw then carved the fuselage so that the rear portion of the canopy would sit down well in its retracted position. In the earlier photograph of the unpainted fuselage the light green area behind the seat is the area I stripped back with a craft knife and sandpaper.

Probably the trickiest surgical job I did was repairing a wheel strut. There are four objects in the following photograph. On the left is a wheel strut from the kit which I was lucky enough to find undamaged on the carpet beside my dogs. Doubtless it got there due to some carelessness of mine. To the right of that is a damaged kit strut I found in the mouth of one of my dogs. The wheel end had been chewed off raggedly but by the time I took this photograph I'd already beveled the end in anticipation of repairing it with a new fragment. The next object is an example of the type of sprue piece I used to carve and sand the strut fragment taking shape on the right.

Then it was a case of splicing together the two pieces. I beveled off the new strut fragment and glued it to the damaged kit strut. I then filled with a little putty and sanded off. It took four evenings of work from discovering the damaged piece to getting to the stage in the photograph below. As I'm sure you can tell, the repaired strut is the one on the left.

I painted both struts flat black then dry-brushed them with aluminum. Then I dusted a little with the weathering powders. The struts are not identical but the repaired piece (still on the left) turned out better than I had hoped for.

Weather

With the color scheme, decals and repairs done, and the last pieces attached, the model was ready for the final stage: making a freshly-painted scale model look like a life-sized, dirty and worn vehicle. This basically involves scaling up the model's shadows and simulating the effects of weather and use. The shadows in the nooks and crannies and panel lines of a 1:48 scale model are barely visible: they do not look like vehicle shadows reduced to 1:48 scale. Applying a thin wash of black or brown darkens and deepens the recesses of the model both improving the shadows and giving the illusion of collected dirt. Other techniques involve applying paint chip effects either with dabs of a bare metal color or masking off prior to painting. Rain streaks, rust and dust are other options.

Before weathering I gave the model another coat of Future floor finish. This seals in the decals and provides a gloss surface so the wash runs off the flat areas yet still pools in the recesses. I made a wash from 1 part black and brown artists' oils with about 9 parts mineral spirits. There were a few places where the wash did run into recesses but most of the panel lines on this model are raised. What worked for me was to place a drop of wash each side of a raised line and then use a fingertip to blend and smooth the paint up into the corner of the panel line. A little dry-brushing along the ridge of the panel line with chrome silver completed the effect. For the paint chips I first tried a silver leafing pen but I wasn't convinced by the results. What I preferred was to place tiny dabs of chrome silver with a fine brush and blend the occasional one with my finger. In other places dry-brushing was effective.

To clean up excess wash I dipped either a rag or a napkin or a Q-tip in mineral spirits and wiped the area down. Using oils for the wash on top of the Future (which is acrylic) meant that the oil thinner would only affect the wash layer. Using an acrylic wash and hence acrylic thinner would have been hazardous to the Future.

Finally I dusted the model with Doc O'Brien's weathering powders; the rusty brown color this time.

Finish

The final sealing coat was flat clear lacquer mixed about 1 to 1 with thinner. I'll leave you with some photographs of the finished model.

Author: "stevewhitepsfd"
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 10 Feb 2007 02:11

This sample shows how to transform glyphs in a TextBlock. The kinds of things you can do here are letter-pair kerning and animating the translation or rotation of individual glyphs.

Attached Media: application/x-zip-compressed ( 41 ko)
Author: "stevewhitepsfd"
Comments Send by mail Print  Save  Delicious 
Date: Wednesday, 25 Jan 2006 00:03

Today the Expression team is delighted to announce the availability of a preview version of Expression Interactive Designer. This preview version is the January 2006 Community Technology Preview [1]

We have compiled a set of sample applications and tutorials specifically for this CTP and you can find them on the official Expression team blog [2].

 

There are lots more resources about Expression on the Microsoft Expression web site. [3]

 

If you enjoyed the previous Channel 9 video [4] featuring the Expression Interactive Designer team then you'll want to check out the new video Robert Scoble hosted and posted today [5]

 

 

[1] http://www.microsoft.com/downloads/details.aspx?familyid=ed9f5fb2-4cfc-4d2c-9af8-580d644e3d1d&displaylang=en

 

[2] http://blogs.msdn.com/expression

 

[3] http://www.microsoft.com/products/expression/

 

[4] http://channel9.msdn.com/Showpost.aspx?postid=115387

 

[5] http://channel9.msdn.com/showpost.aspx?postid=157843

Author: "stevewhitepsfd" Tags: "WPF, Silverlight and Blend"
Comments Send by mail Print  Save  Delicious 
Date: Thursday, 06 Oct 2005 07:07

Microsoft Expression “Sparkle Interactive Designer” (Sparkle for short) was announced and demonstrated at the Professional Developers’ Conference in Los Angeles last month. To find out what this powerful tool is all about, see the Expression Home Page, the Sparkle Team on Channel9, and Eric Rudder’s PDC keynote.

 

So, what is the Sparkle tool good for and who will use it? Well first of all, if you’re evaluating the Windows Presentation Foundation (WPF) today, you’ll have noticed that Visual Studio currently has no design surface for XAML source code. In time, Visual Studio will have design support (codenamed ‘Cider’) for WPF suitable for the needs and wishes of software developers. What Sparkle will offer over and above Visual Studio’s WPF designer is a set of features aimed at professional user-experience designers.

 

The kind of designers I’m talking about have creative and technical skills including graphic design, usability design, and interaction design. The North Face demo (also shown at PDC) is a beautiful and striking example of how WPF brings the development of creative interactions within reach and obviates a specialization in 3D computer graphics.

 

Developers with design sensibilities will also use Sparkle, just like designers with programming sensibilities already use Visual Studio. These skill combinations are very common – what’s less common is to be excessively talented in both spheres. So Sparkle will not ‘turn developers into designers’ nor ‘require designers to be developers’ but it will give the members of large development teams the opportunity to specialize whilst preserving the MSBuild format of projects transferred between Sparkle and Visual Studio.

 

Clemens Vasters has written an excellent blog entry about subject-area specialization in which he discusses what he calls visualization developers. Visualization is a component of interaction and the members of this sector of the development team may equally well be called interaction designers and possibly, for the trickier coding, interaction developers.

 

Which brings me onto what code means and, more importantly, what no code means. The community regularly describes HTML, XAML, C#, VB.NET, etc as code which implies that any formalized, syntactically-constrained encoding is code (whether the logic is declarative or imperative). But often, in demonstrations of WPF and Sparkle, the speaker (myself included!) points out that no code was written and I think this deserves some clarification.

 

Typing XAML into Notepad or Visual Studio is, arguably, coding and the no code assertion is hard to support. Similarly, a Sparkle project with no code is an empty one. Rather, what’s compelling about WPF is that the semantics of the code is incredibly rich so you need less of it. What’s compelling about designing on a surface in Sparkle or Visual Studio is that the tool generates the code for you. It so happens that declarative code is more practical for tools to generate than imperative code and that a design surface is able, in real-time, to reflect edits to declarative source code whereas imperative source code is built before it is expressed. So it’s likely that great tool support, making XAML so friendly, is the reason we often overlook it as code.

Author: "stevewhitepsfd" Tags: "Software, WPF, Silverlight and Blend"
Comments Send by mail Print  Save  Delicious 
Date: Friday, 23 Sep 2005 22:26

I’ve been a member of the Microsoft UK PSfD team for three and a half years now but, beginning on Monday, I’m moving to a new role in Redmond. Being an ADC has definitely been the best job experience I’ve had to date: the application development consultancy work with customers is challenging and rewarding in equal measure and my team-mates have been an inspiration and a great bunch of friends.

Our managers encourage our development in every way even if that means eventually losing us from the team. I’m excited to be moving to the corporate campus in Redmond to join the Expression Interactive Designer team as a technical writer. That means I’ll be producing conceptual writing, tutorials and sample applications. Needless to say, I'll be blogging a lot about what I get up to.

EID's codename is Sparkle and today my colleagues bought me a book by a writer called Sparkle Hayter. They think that kind of thing is funny! ;-)

I, however, am a great fan of Sparkle and I'm sure you will be too.

 

Author: "stevewhitepsfd" Tags: "General"
Comments Send by mail Print  Save  Delicious 
Date: Friday, 08 Jul 2005 16:41
I've removed the SxS articles from the blog now because they've recently been published on MSDN. Please see my MSDNography links section.
Author: "stevewhitepsfd"
Comments Send by mail Print  Save  Delicious 
Date: Thursday, 07 Jul 2005 20:33

Download the FolderTreemap3D sample

(Requires Windows Server 2003 or Windows XP, .NET Framework 2.0 SDK Beta 2 (or Visual Studio 2005 Beta 2), and WinFX Beta 1 RC Runtimes and SDK)

 

Ben Shneiderman developed the treemap style of visualization in the early 1990s in response to the common problem of a filled hard disk. For this application, Professor Shneiderman needed an alternative to the incumbent tools (i.e. File Manager and Explorer) which, although strong at quantitative presentation of one hierarchical level of files at a time, don’t offer the aggregation needed for a high-level, qualitative view. A treemap’s strength is the reverse: perspective (or context) is more important than precision. If you’ve ever trawled up and down through the levels of a hierarchy seeking the largest files and folders as candidates for deletion then you’ll appreciate the perspective a treemap gives.

 

The ‘squarified’ treemap is a refinement which minimizes the aspect ratio of each node rectangle and this is the variation I have used. But with any flat treemap, the depth of hierarchical nesting of a node is not obvious to the viewer. It occurred to me that, if a node’s nesting level is represented by its distance along the z axis, then an orthographic 3D projection would appear to be a flat treemap when viewed from the front but would reveal the spacing along the z axis when rotated. I was also curious to see the same 3D model projected with perspective.

 

I have used color to distinguish folder nodes (transparent) from file nodes (colored dark in proportion to their depth). Examine the image at the beginning of the post. The entire image is a visualization of the %windir%/Microsoft.NET/Windows folder which contains the Avalon runtimes. What does the image tell us? Well, first (and without having to expand any nodes) we can see that the \Windows folder contains a single child folder named \v6.0.4030 which in turn contains the \Avalon folder and a number of files. The \Avalon folder contains one large .msi file at a deeper level than the files inside \v6.0.4030. We get a qualitative sense of the relative sizes of the files and folders – e.g. PresentationCore.dll and PresentationFramework.dll are approximately the same size as one another and both much smaller than avalon.msi. We can also see that there is a large number of small files which we could zoom closer to if we wanted to see their names.

 

The following image moves up a folder and shows, amongst other things, the combined size of the Avalon runtimes (the \Windows folder) in relation to the remainder of the .NET Framework. We can also see that, for example, System.ServiceModel.dll is a little larger than PresentationCore.dll and PresentationFramework.dll.

 

Here are the pieces which go into this sample:

  1. A generic DatatreeNode class used to build a ‘datatree’ of the data to be visualized. Using this extension point, any data which can be represented as a hierarchy (e.g. your Exchange/Outlook folders) can be processed into a treemap.
  2. A routine to recurse into a file system folder and build a datatree from it.
  3. A TreemapNode class (and ancillary classes) used to build a treemap from a datatree.
  4. A routine to arrange the treemap into layers for back-to-front rendering. As the scene uses semi-transparent materials, it is defined back to front to aid correct alpha blending.
  5. A routine to walk the treemap layers from furthest (from the eye) to nearest and to process each node in each layer as follows:
    1. Create a tree of Visuals consisting of a TextBlock inside a Viewbox inside a Border.
    2. Create a VisualBrush from the above and use it as the material on a plane (a MeshGeometry3D) which is placed appropriately on the z axis.
  6. A custom Viewport3D in which to display and manipulate the scene (the same one I introduced in the Nendo Nessie post).

There’s a lot of information to be seen in the images here, but even more information emerges when you are able to manipulate the model yourself with the mouse. Download and build the sample and evaluate it yourself. To toggle mouse manipulation mode, use Ctrl + right-mouse-click. See the Nendo Nessie post for more details.

 

Furthermore, information is always lost when flattening (i.e. projecting) a 3D scene for display on a traditional CRT or LCD monitor. Flat displays rely on artificial depth cues (e.g. perspective or color) to tell the eye how far away an object is. The same 3D data shown on a stereoscopic or a holographic display would preserve depth information so that the eye and brain sense true depth and can more fluently read the scene.

 

It would be an interesting exercise to use the sample’s treemap generation logic inside a custom Panel.

I’ll leave you with another of Ben Shneiderman’s visualizations – structured flowcharts – which may offer an interesting future project for someone to realize in Avalon.

 

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 19 Jun 2005 12:42

Command-line build 2: XAML-only NavigationApplication

In the previous post I showed how to build a very basic C#-only Avalon application. At the end I mentioned that declaring and initializing UI is probably not best done with imperative code. This time I’ll go to the other extreme and declare a very simple application entirely in markup. In future posts I’ll settle for a mixture of markup and code-behind.

 

If you’re familiar with ASP.NET then you’ll know about markup files and code-behind files. The idea is that UI is defined in markup, and application logic is separated out into the code-behind file. This way, in an idea world, a developer can drop a basic UI into markup, make it functional in the code-behind, then let a designer take the markup and make it beautiful. It also means that the UI and application logic needn’t be compiled at the same time.

 

Although Windows Forms doesn’t have markup, it does have the InitializeComponent method into which the Forms Designer writes a lot of UI initialization code. This gives some separation of static layout from application logic but, because the UI is initialized in imperative code, it’s not as toolable as markup. It also means the UI and application logic must be compiled together.

 

XAML is Avalon’s markup. XAML can be used to declare any CLR object and it’s effectively a persistence format for CLR objects. When used with Avalon, XAML is a persistence format for Avalon objects, and Avalon offers far better flexibility and customization than ASP.NET or WinForms. XAML is XML so it is extremely toolable and it can be parsed and/or compiled separately from the application logic, even being loaded dynamically at runtime as a control tree.

 

With the Beta 1 RC bits, the Application we created in the previous post purely in C# can’t be done purely in XAML (I’m told it will be possible in future bits). However, we can do a NavigationApplication purely in XAML. A navigation application has a similar paradigm to a web application or a Wizard in that it has pages between which the user nagivates and a Journal in which navigation history is remembered.

 

First we’ll create a file in which to declare the application class. Create a folder called XAML-only NavApp and, in it, create a new text file called NavApp.xaml. Declare an empty NavigationApplication element with a StartupUri of Page1.xaml like this:

 

<NavigationApplication xmlns="http://schemas.microsoft.com/winfx/avalon/2005" StartupUri="Page1.xaml"/>

 

In XAML, elements correspond to type names and attributes correspond to property names (unless recognised by XML, e.g. the default XML namespace declaration). What we’re doing here is declaring a partial type deriving from System.Windows.Navigation.NavigationApplication. We’ll shortly be processing this markup through a XAML markup parser. The markup parser will know the NavigationApplication type because we’ve specified a default XML namespace which identifies the Avalon types. I haven’t named the derived type so it’ll get a default name (actually _Application). The markup parser will also assume we want a singleton instance of this class and it will generate the code to instantiate one also. We’ll look more closely at what gets generated from this XAML after we’ve built it.

 

Next, create Page1.xaml containing a Page element as follows:

 

<Page xmlns="http://schemas.microsoft.com/winfx/avalon/2005" Text="Hello from Page1">

     <TextBlock>

          <Hyperlink NavigateUri="Page2.xaml" Text="Go to Page2"/>

     </TextBlock>

</Page>

 

Again the Avalon XML namespace is required. The value of the Page element’s Text attribute will appear in the navigation application’s main window caption when this page is shown. Nested inside the Page element is a TextBlock element which is a control used to display simple text content. The markup parser has a set of rules by which it determines what a child element represents relative to its parent. A child element may be a complex property of its parent (e.g. Button.Background); a member of the collection stored in its parent’s default property; part of its parent’s content tree; or something else.

 

In this case the TextBlock is interpreted as being the value of the Page’s Child property (which is of type UIElement; and TextBlock is a UIElement). Inside the TextBlock is a Hyperlink element which is interpreted as the TextBlock’s content.

 

Again, this XAML is declaring a new partial type deriving from Page. Whereas the markup parser will instantiate an application instance for us without being explicitly asked, it does not do so for other classes declared in XAML. However, the application’s StartupUri is set to Page1.xaml which is a fairly explicit request for an instance of our Page-derived class and the markup parser will generate code which will result in one. As I’ll show in a moment, this instance is actually created at runtime by another parser.

 

Next, create Page2.xaml:

 

<Page xmlns="http://schemas.microsoft.com/winfx/avalon/2005" Text="Hello from Page2"/>

 

Now create a project file called NavApp.csproj which contains:

 

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>

    <AssemblyName>NavApp</AssemblyName>

    <OutputPath>.\</OutputPath>

    <OutputType>winexe</OutputType>

  </PropertyGroup>

  <ItemGroup>

    <Reference Include="System" />

    <Reference Include="WindowsBase" />

    <Reference Include="PresentationCore" />

    <Reference Include="PresentationFramework" />

    <ApplicationDefinition Include="NavApp.xaml" />

    <Page Include="Page1.xaml" />

    <Page Include="Page2.xaml" />

  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

  <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" />

</Project>

 

The NavApp.csproj file contains the same Assembly references as the project file in the previous post, but it also has ApplicationDefinition and Page item types. These item types are built by code inside the PresentationBuildTasks.dll I mentioned in the previous post, and the WinFX targets tell MSBuild about that dll.

 

Choose Start – All Programs – WinFX SDK – Release Build Environment and change directory to your XAML-only NavApp folder. Issue the command msbuild and confirm that the build succeeded.

 

If you can resist running the application right away you might be interested to look at the generated intermediate files in your \obj\release folder. The .baml files contain a binary version of the XAML (i.e. tokenized XAML). The .g.cs files are generated C# source files.

 

When we built our project, the Page XAML files were parsed into a corresponding .g.cs source file and a corresponding .baml file. Inside Page1.g.cs you’ll see that a class called _Page1 has been generated. In this class is logic to load the page’s BAML from a managed resource embedded in the assembly. However, although Connect is called (the purpose which is to give the class the opportunity to wire up any event handlers), InitializeComponent is not, as can be witnessed by setting breakpoints. A class called System.Windows.Navigation.NavigationService is actually used behind the scenes to load the BAML and parse it into an tree of user-interface elements.

 

Inside NavApp.g.cs (which was generated from NavApp.xaml) the _Application class is defined, deriving from NavigationApplication. And in its constructor the StartupUri is set to the same value we set in markup.

 

NavApp.Main.g.cs does not correspond to any XAML file but it is generated by virtue of the fact that we are building an application. Our Main method is generated in this class along with a ResourceLoader class which you can see being instantiated in the _Application class. However, the ResourceLoader is now a deprecated mechanism. In the Main method our application singleton instance is created, and it is stored in a private static member by the Application base class constructor. This enables the instance to be accessed via System.Windows.Application.Current as you can see happening in _Page1.MyApplication.

 

Also during the build process, the generated .g.cs source files are then compiled into an assembly. All that remains of the markup is the BAML which is deserialized into CLR objects at runtime by the System.Windows.Serialization.Parser class. This class can be used to (de)serialize any BAML or XAML at runtime.

 

If you now run the navigation application you will see the chrome at the top of the window which contains the navigation buttons. The chrome actually belongs to an instance of a NavigationWindow which has been automatically created for us, and our Pages are placed inside that. The Journal is the name for the mechanism which remembers our navigation history which you can see by using the navigation buttons’ drop-down buttons after you have navigated with the hyperlink.

 

Next time I’ll move into Visual Studio 2005 and combine XAML with code-behind in order to benefit from the advantages of each.

 

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 18 Jun 2005 14:21

I thought it would be interesting to walk through building some very basic Avalon applications. Some topics I want to introduce include Avalon’s application model; the interplay between declarative XAML markup and imperative CLR code-behind; what happens at build time; and some behind-the-scenes details at runtime.

 

The WinFX Beta 1 RC bits

To follow along you’ll need to install the WinFX Beta 1 RC Runtimes and SDK on XP or Windows Server 2003 if you haven’t already.

 

Although Avalon and Indigo are each parts of WinFX (i.e. the Windows Frameworks), their assemblies are installed to slightly different destinations in the Beta 1 RC. For instance, Indigo’s System.ServiceModel.dll can be found in %WINDIR%\Microsoft.NET\Framework\v2.0.50215. But the Avalon runtimes (WindowsBase.dll, PresentationCore.dll and PresentationFramework.dll, etc) can be found in %WINDIR%\Microsoft.NET\Windows\v6.0.4030. This separation may become clearer on Longhorn but it suggests that Indigo is part of the .NET Framework whereas Avalon is part of WinFX proper. This is supported by the following table:

 

Assembly

AssemblyProductAttribute

AssemblyVersion

AssemblyVersion of .NET F/W Referenced

System.ServiceModel

Microsoft(R) .NET Framework

2.0.0.0

2.0.0.0

WindowsBase

Microsoft (R) Windows (R) Operating System

6.0.4030.0

2.0.0.0

PresentationCore

Microsoft (R) Windows (R) Operating System

6.0.4030.0

2.0.0.0

PresentationFramework

Microsoft (R) Windows (R) Operating System

6.0.4030.0

2.0.0.0

 

Another of Avalon’s assemblies is PresentationBuildTasks.dll which contains the MSBuild Tasks which process XAML into CLR source code files and into a binary representation called BAML.

 

The first two applications will use command-line builds; I’ll get to Visual Studio 2005 later.

 

Command-line build 1: C#-only Application

Let’s begin by building an Avalon application entirely in C#. Create a folder called C#-only App and, in it, create a new text file called App.cs. Add the following code to the file:

 

using System;

 

class EntryPoint

{

     [STAThread]

     static void Main() {}

}

 

So far there is nothing to distinguish this from a regular .NET application. It has a UI thread and an entry point. Now add a using statement for System.Windows. Notice the subtle difference here: if we were writing a Windows Forms application we would use System.Windows.Forms. Next, in Main, instantiate a new Application (actually System.Windows.Application) and call its Run method. Your file should now look like this:

 

using System;

using System.Windows;

 

class EntryPoint

{

     [STAThread]

     static void Main()

     {

          Application app = new Application();

          app.Run();

     }

}

 

If we build and run this, we’ll have a running Avalon application but it will have no way of interacting with the user (unless you count Task Manager!). So let’s have the app show a window. In Main, instantiate a new Window (System.Windows.Window) and call its Show method. Your Main method should look like this:

 

     static void Main()

     {

          Application app = new Application();

          (new Window()).Show();

          app.Run();

     }

 

We’ll be using the Microsoft Build Engine (MSBuild) to build our application, so create a project file called App.csproj in your application folder. Inside it put the minimum contents to perform an Avalon build:

 

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>

    <AssemblyName>App</AssemblyName>

    <OutputPath>.\</OutputPath>

    <OutputType>winexe</OutputType>

  </PropertyGroup>

  <ItemGroup>

    <Reference Include="System" />

    <Reference Include="WindowsBase" />

    <Reference Include="PresentationCore" />

    <Reference Include="PresentationFramework" />

    <Compile Include="App.cs" />

  </ItemGroup>

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

</Project>

 

The only thing of note, the only part which is different from a normal C# MSBuild project, is the set of assemblies referenced (the ones we talked about earlier).

 

Now, to build the application from a command-prompt choose Start – All Programs – WinFX SDK – Debug Build Environment and at the prompt change directory to your C#-only App folder. Issue the command msbuild. Confirm that the build succeeded.

 

Run App.exe and note the default window which is shown. Now, to customize the window a little. Add a new class to App.cs called MyWindow which derives from Window. In the class’s constructor set the window’s Text to “Hello from MyWindow”.

 

class MyWindow : Window

{

     internal MyWindow()

     {

          this.Text = "Hello from MyWindow";

     }

}

 

Change the code in Main so it instantiates a MyWindow instead of a Window. Build and run again and note the window’s caption is the value you set the Text property to.

 

So far there’s nothing to distinguish this as an Avalon window so let’s put some Avalon controls inside it. Add a using statement for System.Windows.Controls. In MyWindow’s constructor, declare an object reference and assign a new Button (System.Windows.Controls.Button) to it. Cast the object to a ContentControl and set its Content to “Some text content”. Finally set the MyWindow’s Content to the object.

 

     internal MyWindow()

     {

          this.Text = "Hello from MyWindow";

          object o = new Button();

          (o as ContentControl).Content = "Some text content";

          this.Content = o;

     }

 

Notice how both the Button and the MyWindow have a Content property of type object. This is because both derive from System.Windows.Controls.ContentControl. This idea that there is no constraint on what can be contained within a control is Avalon’s evolution of text content. In the above code the Button’s content is still plain old text but it could be any object whatsoever (including the root of a tree of content), e.g. a Shape, a Control, a Panel or a business object. The MyWindow’s content is a Button, but would normally be a Panel of some kind inside which the remainder of the window’s content would be laid out.

 

I made the variable o have type object to show that the Content property of the MyWindow is of type object. But this also enables us to instantiate any ContentControl and assign it to o. Try instantiating a CheckBox instead of a Button.

 

Build and run. Notice that the Button is filling the window. This is because the default behavior for Buttons is to stretch to fill their container. There are many rules around layout which I’ll cover in a later post. For now, though, cast the Button object to a FrameworkElement and set its horizontal and vertical alignment to Center and, so that we can see it clearly, set its LayoutTransform to new ScaleTransform(5,5). You’ll also need to add a using statement for System.Windows.Media which is the namespace containing the ScaleTransform class. Your entire code file should finally look like this:

 

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

 

class EntryPoint

{

     [STAThread]

     static void Main()

     {

          Application app = new Application();

          (new MyWindow()).Show();

          app.Run();

     }

}

class MyWindow : Window

{

     internal MyWindow()

     {

          this.Text = "Hello from MyWindow";

          object o = new Button();

          (o as ContentControl).Content = "Some text content";

          (o as FrameworkElement).HorizontalAlignment = HorizontalAlignment.Center;

          (o as FrameworkElement).VerticalAlignment = VerticalAlignment.Center;

          (o as FrameworkElement).LayoutTransform = new ScaleTransform(5,5);

          this.Content = o;

     }

}

 

The casts are there only to highlight which classes define the various properties. If you like you can change o’s type to Button and remove all the casts. Build and run and notice the difference to the Button’s layout and scale transformation.

 

So far the application consists exclusively of imperative code which would arguably be more suitable in the form of declarative XAML markup. In the next post I’ll look at a XAML-only application (a NavigationApplication in fact) and after that we’ll mix the two modes and begin to use Visual Studio 2005.

 

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Monday, 11 Apr 2005 19:30

Download the ArthurTest sample

Download nessie.obj

Just before I started working at Microsoft nearly three years ago, I wrote a hobby project called Windows OpenGL Classes (WOC). It’s written in VC++ 6.0 (but it compiles with VS.NET 2002) and it’s a kind of MFC for OpenGL. So it provides classes for application and window, as well as scene-graph and rendering management, and even a very flexible declarative animation system. It features geometry-generation and normal-calculation and the ability to read and write Wavefront OBJ files. The main feature missing from WOC is picking (i.e. selection, or hit-testing). I never got round to implementing picking, so I never got to experiment with 3D Windows controls which is something I’m greatly interested in.

 

Of course, Avalon provides most of the above features so I thought it’d be interesting to see if there were any parts of WOC which would add value to Avalon. For this experiment I’ve been using the March CTP of Avalon, running on Windows XP SP2. By the way, if you’d like a primer on 3D in general and Avalon in particular I recommend Daniel Lehenbauer’s blog (http://blogs.msdn.com/danlehen). I’ve called my new project Arthur, and there’s a screenshot of it above. The three main features which I’ll talk about in this post are: interactive camera manipulation, geometry generation, and geometry loading.

 

Help yourself to the ArthurTest sample source code from the link above. In Arthur\Viewport3D.cs you’ll find the definition of a class derived from Avalon’s System.Windows.Controls.Viewport3D. The added value of Arthur’s Viewport3D is to provide mouse manipulation of the camera. Depending on whether the symbol DX is defined, mouse input is handled either via DirectInput (for which you’ll require the DirectX 9 SDK) or via normal mouse input. By default, mouse manipulation is inactive for a viewport. In order to toggle into and out of mouse manipulation mode, use Ctrl+right mouse button. Once in mouse manipulation mode, if you depress both left and right mouse buttons whilst moving the mouse you will pan the scene. If you depress only the right mouse button whilst moving the mouse you will zoom the camera. If you don’t depress either button then you will effectively rotate the entire scene (lights and all). The rotation is actually achieved by moving the camera over the surface of an imaginary sphere. Up/down mouse motion affects the camera’s latitude (clamped to the range [0,180]), and left/right mouse motion affects the camera’s longitude.

 

There is some geometry generation code in Arthur\MeshGenerator.cs – I plan to add to it in time. You can use the static methods to generate meshes, and specify whether you want texture coordinates to be generated. Do be aware, though, that if you choose not to generate texture coordinates then you shouldn’t use an ImageBrush for your material otherwise nothing will be seen. Incidentally, the sphere’s geometry is calculated so that if you do set its material to an ImageBrush, the image will be upright with its center facing the default camera position.

 

Finally, in Arthur\FileLoaders.cs, you will find code to read geometry from Wavefront OBJ files. The ArthurTest sample uses this feature to read in a file called nessie.obj. It’s actually a textured model I created using Nendo 1.1. However, it isn’t textured in the screen shot above because the way OBJ files specify texture coordinates isn’t compatible with Avalon. I need to do some work yet to handle that difference. Another constraint is that the code currently only handles OBJ files having a single group in them.

 

So with the ability to load OBJ files we have an easy way to define geometry. I can use simple OBJ files to demonstrate how Avalon calculates normals when they are not supplied. The following OBJ file content defines two triangles at an angle to one another, sharing two common vertices. For this geometry, Avalon calculates vertex normals and the result is smooth-shading.

 

v -0.5 -0.5 0.5

v -0.5 0.5 0.5

v 0.5 0.5 0.5

v 0.5 -0.5 0

f 1 4 3

f 1 3 2

 

This next OBJ file content defines the same two triangle but this time there is no vertex sharing. For this geometry, Avalon calculates face normals and the result is flat-shading.

 

v -0.5 -0.5 0.5

v -0.5 0.5 0.5

v 0.5 0.5 0.5

v -0.5 -0.5 0.5

v 0.5 0.5 0.5

v 0.5 -0.5 0

f 4 6 5

f 1 3 2

 

As WOC handles its own normals, it can calculate face or vertex normals on request. Arthur doesn’t have that feature yet but it’s on my wish-list. If you do experiment with OBJ files, remember that Avalon (and the OBJ file format) uses a right-hand coordinate system and therefore triangles should be wound counter-clockwise. The ‘v’ and ‘f’ markers signify vertex data (x,y,z values) and face data (either triangles or quads) respectively. Make sure there’s a carriage-return between each set of data.

 

I no longer need WOC’s animation features. But in WOC, just like in Avalon, a camera is a model and can therefore be animated. WOC’s animations are provided by relays of signal-generating objects feeding into chains of functions, and ultimately bound to the properties of models. This way position, colour, etc can be animated. You can see some examples of this animation system in the Graphics Samples section of my website.

 

So what’s next? Well, because Avalon intrinsically provides most of WOC’s value proposition, there’s actually not a great deal more of WOC to port. There are one or two more geometry-generation methods to add (including my favorite, the ripple-grid). I’m very excited by what Avalon has to offer, and I’m looking forward to playing with its picking features to finally do those experiments with 3D controls I’ve been wanting to do. Watch this space!

Author: "stevewhitepsfd"
Comments Send by mail Print  Save  Delicious 
Date: Monday, 14 Mar 2005 00:52

If, like me, you've been awaiting an update on Mark Lucente's research, you'll find this paper by Tyeler Quentmeyer et al fascinating: http://web.media.mit.edu/~vmb/papers/quentmeyerms.pdf

 

Apparently (http://www.media.mit.edu/spi/) the Spatial Imaging Group at MIT disbanded about the time this paper was published (almost a year ago). I hope this important research is continuing somewhere and is getting enough funding.

Author: "stevewhitepsfd" Tags: "General"
Comments Send by mail Print  Save  Delicious 
Scales   New window
Date: Saturday, 12 Mar 2005 20:59

So I’ve talked about classes representing the ideas of note and interval. This post I’ll cover Voices.ScaleClass, Voices.Scale and Voices.KeySignature.

 

A scale is an interesting interplay between notes and intervals within an octave. As an example, the notes C D E F G A B constitute the C major scale. But it is the set of intervals between these notes (the sum of which is an octave) which defines the essence of what it is to be a major scale. Specifically, these intervals are: maj2 maj2 min2 maj2 maj2 maj2 min2. Typically the intervals are summed cumulatively with the initial perfect unison and the final perfect octave assumed, so: maj2 maj3 per4 per5 maj6 maj7. That set of intervals, measured out above a tonic note, locates and names the notes of any major scale.

 

Although a scale can be viewed as a series of notes or as a series of intervals, it’s practical to see the notes as the scale and the intervals as the scale class. So a scale can be defined as a sequence of notes, chosen out of the possible notes in the octave, and beginning on a tonic. And a scale class can be defined as the class of scales between whose notes appears the same sequence of intervals. As I’ve said, that sequence of intervals sums to an octave no matter what the scale class.

 

So, let’s look at a C# class representing scale class. Greatly simplified, Voices.ScaleClass looks like:

 

public class ScaleClass

{

      static ScaleClass()

      {

            _majorScale = new ScaleClass("Major", "2 3 4 5 6 7");

            _dorianMode = new ScaleClass("Dorian Mode", "2 b3 4 5 6 b7");

            ...

            _bluesScale = new ScaleClass("Blues Scale", "b3 4 b5 5 b7");

      }

 

      public static ScaleClass MajorScale { get { return _majorScale; } } static ScaleClass _majorScale;

      public static ScaleClass IonianMode { get { return _majorScale; } }

      public static ScaleClass DorianMode { get { return _dorianMode; } } static ScaleClass _dorianMode;

      ...

      public static ScaleClass BluesScale { get { return _bluesScale; } } static ScaleClass _bluesScale;

 

      internal ScaleClass(string longName, string intervalsString)

      {

            _longName = longName;

            _intervalsString = intervalsString;

      }

      internal string _longName;

      internal string _intervalsString;

}

 

The only real value this class provides is a place to store the _intervalsString field. This field contains a string representation of the sequence of intervals which give the scale class its identity. These intervals have the format of an optional sharp or flat symbol followed by a digital interval quantity. Alternatively they can be the solfeggio symbols: do, di, ra, re, ..., te, ti.

 

The class Voices.Scale has a constructor with the signature:

 

public Scale(ScaleClass scaleClass, Note tonic)

 

What this constructor is interested in is the tonic note and the _intervalsString from scaleClass. It String.Splits intervalsString into a string[] the elements of which it then takes in turn and obtains an Interval from by means of the following method on Voices.Interval:

 

internal static Interval Interval.LookUp(string abbreviation)

 

The constructor proceeds to add each resulting Interval in turn to the tonic Note, thus obtaining the degrees of the scale. It’s a little more complicated than than because Voices.Scale is actually composed of a doubly-linked cyclic list of Voices.ScaleTone.

 

So, of the list nodes (i.e. the tones) in a Scale, those which are ScaleDiatones are the ones corresponding to the tonic note and the notes reached by adding the intervals of the scale class to it. All the rest are plain old ScaleTones.

 

In order to support enumeration, Voices.Scale implements IEnumerable and its implementation of IEnumerable.GetEnumerator simply returns a new instance of the Voices.ScaleToneEnumerator class. As is typical, ScaleToneEnumerator Resets its Current state to ‘one before the first element’ which in this case is the tone at the 11-o’clock position. It implements MoveNext by moving to ScaleTone.Sharp until the 11-o’clock position is reached again.

 

The last class I’ll talk about in this post is KeySignature. A key signature is a pattern of sharp or flat symbols written at the beginning of a musical staff to indicate which degrees of the scale are not natural. Strictly speaking, distinct key signatures exist only for fifteen major scales. Minor scales and the remaining modes re-use the key signatures of their relative major scale. I omitted this detail above for the sake of clarity, but one of the arguments to the ScaleClass constructor is a value from the ScaleClass.Mode enumeration, which looks like this:

 

      public enum Mode

      {

            Major = 0,

            Dorian = 6,

            Phrygian = 5,

            Lydian = 4,

            Mixolydian = 3,

            Minor = 2,

            Locrian = 1

      }

 

There is a field for each mode. The value given to each field represents the degree of the corresponding mode on which the mode’s relative major begins. For example, you may know that the major mode begins on the minor mode’s third degree. This is why Minor has the value 2 (where 0 means first). The constructor of the class Voices.Scale reads n, the integer value of its ScaleClass’s Mode, and then finds the nth degree of the scale being constructed. This way it identifies the major scale on which the scale is based and it is that scale which donates its key signature.

 

The important parts of the KeySignature class are:

 

      public Note[] Accidentals

      {

            get

            {

                  return _accidentals;

            }

      }

      internal Note[] _accidentals;

 

      public bool Sharps

      {

            get { return _sharps; }

      }

      internal bool _sharps = true;

 

The Accidentals property returns an array of Notes in key signature order, and the Sharps property tells us whether the accidentals are sharps or flats.
Author: "stevewhitepsfd" Tags: "Music theory, Voices, Software"
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 27 Feb 2005 20:42

So, I spent the past two weekends and every evening between finishing these. Please check them out and let me know what you think.

Registration-Free Activation of COM Components: A Walkthrough

Registration-Free Activation of .NET-Based Components: A Walkthrough

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Monday, 21 Feb 2005 04:27

I posted the article "SxS Managed COM With Manifest Resource (WinXP and Win2K3)" some time ago and Jason Buxton was interested in applying it to Visual Basic 6.0 client applications. Well, I've put together an MSDN article proposal which addresses that question and is a general improvement on the original article.

The new article is called Registration-Free Activation of .NET-Based Components: A Walkthrough and can be found in the Software category of my articles section. I'm planning accompanying articles named "Registration-Free Activation of COM Components: A Walkthrough" and "Registration-Free COM in Web Applications: A Walkthrough."

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Friday, 18 Feb 2005 08:18

In the previous post in the Voices category I showed my re-imagined Voices.Note class and its close relatives. You can already see that the new design has a useful separation of tone from note. I had also mixed solfeggio and scale into my initial, abandoned, design. I’ll come to scale in the future but, in this post, I’ll show why solfeggio is, and should remain, distinct from note. At the same time I’ll introduce the second fundamental of music - interval. By the way if you want to know more about music theory check out the articles I’ve posted under the Voices Help category. These articles will be developed further over time.

 

So, the reason I’d made a horrific hybrid of solfeggio and note the first time round (like Seth Brundle spliced with the fly) was because I hadn’t appreciated what solfeggio is, or at least what the best way to interpret solfeggio is. Warburton’s Harmony is not alone in presenting solfeggio as a kind of algebra for notes. You’ll find many definitions describing the solfeggio syllables as the ‘notes of a scale’, and very few point out that they’re more usefully thought of as aliases for intervals above some scale tonic. So do is equivalent to perfect unison; di is augmented unison; me is major third; is minor third, and so on.

 

With solfeggio and interval neatly unified, I’ll now turn to interval itself and show how I implemented and optimised it in the Voices.Interval class. The kind of client code I want the Voices class library to be able to support is:

 

Note n1 = Note.C;

Interval interval = Interval.Second.Major;

Note n2 = n1 + interval.Inverse;

 

If you have experience of music theory you’ll know that an interval has two components – quality (e.g. major) and quantity (e.g. second). In my first, abandoned, version of Voices.Interval I gave the class just such fields. On top of those I gave it fields storing the number of compound intervals (for intervals greater than an octave) and the number of times the interval was diminished or augmented (which could be zero). It took me a long time and about 900 lines of C# to get the Interval class correct in its first version. Its methods (e.g. DecrementQuantity and IncrementQuantity), properties (e.g. Octaves) and operators were long and full of tortuous boundary condition logic.

 

What I’d missed is that there was no need to represent the state of an interval so literally. It eventually occurred to me that every note is some interval above or below C4. And you can represent the private state of any interval – ascending or descending, simple or compound – by the note which is that interval away from C4. It only remained to implement the properties in terms of that internal state by reusing the Voice.Note class and the methods, properties and operators I’d already implemented on it. This change was done surprisingly quickly and it was a real education to me that note and interval really are two aspects of the same idea. In lines of code the new class is well over a third shorter than its first incarnation. An extreme example is the Octaves property’s set clause which was reduced from 64 lines to 1 because Voices.Note has its own Octaves property.

 

The new Voices.Interval class, plus its nested and ancillary types, is around 2,500 lines of C# and it looks like this:

 

public class Interval : IComparable

 

Public Ancillary Types

class IntervalException : ApplicationException

enum IntervalQuantity

enum IntervalQuality

 

Public Nested Types

class GeneralIntervalList : IList, IEnumerator

abstract class GeneralInterval : IList, IEnumerator

class Unison : GeneralInterval

class Second : GeneralInterval

...

class Fifteenth : GeneralInterval

 

Public Fields

static bool NameIsAbbreviated

static bool NameIncludesCompoundText

static bool NameIncludesDirection

 

Public Constructors

Interval(Interval)

Interval(Interval interval, Int32 additionalAlteration)

Interval(Interval interval, Int32 additionalAlteration, Int32 additionalOctaves)

Interval(Interval interval, Int32 additionalAlteration, Int32 additionalOctaves, bool reverseDirection)

 

Public Properties

static Unison GeneralUnison { get; }

static Second GeneralSecond { get; }

...

static Fifteenth GeneralFifteenth { get; }

bool IsImmutable { get; }

bool IsAscending { get; }

Interval Complement { get; }

Interval Inversion { get; }

Interval Reverse { get; }

Int32 Alteration { get; set; }

Int32 Octaves { get; set; }

IntervalQuantity Quantity { get; set; }

IntervalQuality Quality { get; set; }

string CompoundTextTextual { get; }

string CompoundTextDigital { get; }

string AlterationText { get; }

string Name { get; }

Int32 Semitones { get; }

bool IsCompound { get; }

bool CanBePerfect { get; }

Interval SimpleInterval { get; }

 

Public Methods

void DecrementQuantity()

void IncrementQuantity()

void Diminish()

void Augment()

string GetName(bool abbreviated)

string GetName(bool abbreviated, bool includesCompoundText)

string GetName(bool abbreviated, bool includesCompoundText, bool includesDirection)

static bool Exists(IntervalQuantity quantity, IntervalQuality quality)

string ToString()

static Interval operator+(Interval lhs, Interval rhs)

static Interval operator-(Interval lhs, Interval rhs)

static bool operator==(Interval lhs, Interval rhs)

static bool operator!=(Interval lhs, Interval rhs)

static bool operator>(Interval lhs, Interval rhs)

static bool operator>=(Interval lhs, Interval rhs)

static bool operator<(Interval lhs, Interval rhs)

static bool operator<=(Interval lhs, Interval rhs)

bool Equals(object obj)

bool Equals(Interval rhs)

bool IdenticalTo(Interval rhs)

int GetHashCode()

int CompareTo(object arg)

 

By the way, I made Voices.Note a value type as I know I’ll be using a lot of Note[]. I don’t suspect I’ll be doing that with Interval, so I’ll leave it a reference type until there’s any good reason to change it.

Author: "stevewhitepsfd" Tags: "Music theory, Voices, Software"
Comments Send by mail Print  Save  Delicious 
Date: Thursday, 17 Feb 2005 08:48

Appendix A – Definitions

Accidentals

Accidentals are the sharp/flat/natural (//) symbols in a note’s name. A note with either no accidentals or with a natural symbol in its name is natural. Each sharp or flat symbol in a note’s name indicates that the note has been sharpened or flattened respectively from its natural form.

 

Flatten

When a note is flattened, its pitch is lowered by one semitone, thereby shifting it counterclockwise on the twelve-tone clock. Flattening a sharpened note moves it back clockwise towards the natural note.

 

Frequency

A term meaning rate of oscillation. An oscillator completes a particular number of oscillations, or cycles, per second. This rate is physical in that it can be measured with instruments or calculated from other properties. It is called the frequency of the vibration and its unit of measurement is cycles per second, also known as Hertz (Hz for short). A sound with a smaller number of Hz is said to possess a lower frequency than one with a larger number of Hz, which is said to have a higher frequency.

An oscillator can produce a single frequency, or it can produce many. A pendulum has just one frequency. A harmonic oscillation such as a single note played on a guitar-string produces a fundamental frequency and, at the same time, a series of other more subtle frequency components known as overtones. Whether a single or multiple frequencies are produced by a musical oscillator, they maintain their rate even as the amplitude diminishes.

 

Harmonic oscillation

Motion characterized by a regular change in position and direction. A pendulum oscillates; its behavior is also called (simple) harmonic motion. Each complete back-and-forth motion is one oscillation, or cycle. Similarly, waves and vibrations are oscillations. A musical instrument has parts which vibrate: a plucked guitar-string, for instance.

            Harmonic oscillation is regular in that the number of oscillations per second – the frequency, or rate of oscillation – does not vary over time (except whilst deliberately being modified, e.g. bending a guitar-string). Even when a pendulum or a vibrating guitar-string loses its energy, it continues to oscillate at the same rate until it stops. This is a quality of oscillation crucial for tonal music to work. If notes arbitrarily changed their pitch whilst being played, it would be impossible to predict the nature of their interaction, and thus impossible to make tonal music with them.

 

 (Harmonic) overtone series

The series of frequencies which vibrate in harmony with a fundamental frequency. Overtone frequencies are simple integer multiples of the fundamental frequency and, being components of sounds produced in the natural world, are ratios the ear finds natural. Overtone ratios early in the series are the most important to the theory of tonal harmony and to the construction of the frequency ratios used to make music.

 

Interval

An interval is the distance between two notes. Notes are complex, consisting as they do of a named tone and an alteration. And the distance between them is also complex because intervals consist of both a quantity and a quality.

An interval’s quantity is counted from the first note in the sequence and named for the last. So C up to D is called a second because D is the second of the sequence. And G up to B is a third. If you know an interval’s quantity then you know the general interval. If you also know the interval’s quality then you know the specific interval. By way of analogy you could say that knowing a note’s alphabetic name is knowing the general note; and also knowing its alteration is knowing the specific note. Any C to any D is a general second. If we can be specific about the C and the D then we can be specific about the second. For example the interval between C and D is a major (which means larger, or greater) second.

You can think of the interval between two natural notes as the natural interval between them. The natural intervals above C are special and their sizes are the default sizes for intervals – all qualities of intervals are defined relative to these default sizes. Seconds, thirds, sixths and sevenths can be diminished, minor, major (the default) or augmented; unisons, fourths, fifths and octaves can be diminished, perfect (the default) or augmented.

Intervals larger than an octave are compound intervals. Every interval has a direction: either ascending (positive) or descending (negative). Therefore F up to A and F down to A differ in both magnitude and direction; whereas F up to A and A down to F differ only in direction.

The operations which are defined for intervals are: addition of two intervals, giving an interval; and addition of an interval to a note, giving a note. Subtraction is defined by the addition operator, after reversing the direction of the second operand.

 

Note

The term note is overloaded with meaning. Sometimes the physical divisions on an instrument (piano-key, fretted guitar-string) are referred to as notes. But also, like tone, the specific pitches produced by a tuned musical instrument are known as notes.

Each instrument tone corresponds to several possible notes, distinguished by their different note names and existing for different musical circumstances. So, although a note uniquely identifies a tone on the twelve-tone clock, the converse is not true. For example, C and D are different notes which identify the same tone in common tunings. In cases such as this, the choice of name – the tone’s spelling – depends on harmonic context. The semantic of note is more complex than that of a pitch or a tone. Tones are measured simply by their twelve-tone clock position, whereas a note’s clock position and name are found by adding an alteration to a named tone. So, a note’s name gives directions for how the clock position it occupies is reached.

A note takes the alphabetic part of its name from its named tone. The alteration, which can be zero, indicates the direction and distance in semitones the note’s clock position is relative to the named tone. Moving counterclockwise on the twelve-tone clock takes you lower in pitch – descending – and moving clockwise takes you higher in pitch – ascending. In music, lowering pitch is known as flattening, and raising pitch is known as sharpening. A note’s alteration, if it is not zero, is written as a series of either sharp () or flat () symbols known as accidentals.

A simple example is the note C whose named tone is C and which has no alteration. It is therefore at the same position as tone C at 12 o’clock. The path to the note C also begins at tone C but is sharpened (raised a semitone in pitch, clockwise) once, so it occupies the 1 o’clock position. The note B and the flattened note C both occupy position 11 and they identify the same tone but they are not the same note because they give different names, or spellings to the tone.

When its alteration is zero, you may optionally write a natural () accidental in a note’s name to indicate that the note shares the natural name and position of its tone. For example, the note C can be called C to make it clear you haven’t missed a symbol off a C or a C. Another accidental is the double-sharp (x), which makes, for example, Cx a concise form of C♯♯.

It should be clear that the natural name, if any, of the tone identified by a note needn’t bear any relation to the note’s own name. For example, the note Cx occupies position 2, the same position as tone D, but D does not appear in the spelling of this note. What’s important is the name of the tone we begin from and the magnitude and direction of the alteration.

The operations which are defined for intervals are: subtraction of one note from another, giving an interval; and addition of an interval to a note, giving a note. Subtraction of an interval from a note is defined by the addition operator, after reversing the direction of the interval.

 

Octave

Consecutive tones are grouped together into sets of twelve, called octaves. In common tunings, the tones in an octave are spaced approximately equally in pitch even though their actual frequencies vary logarithmically.

Octave is also used to describe the musical interval between same-named notes in two neighboring octaves. The frequency ratio of these equivalent notes in octave n and octave n-1 is 2:1. This straightforward relationship causes a similarly straightforward aural effect. When played either in succession or together, the two tones are perceived to have an unmistakably similar quality.

 

Pitch

Frequency is a physical property of an oscillator. Pitch is the subjective, mental sensation of frequency and, since the mind is the measuring instrument, pitch can’t generally be measured or described with great accuracy. Pitches are perceived as low and high in proportion to the frequency of the sound being heard.

 

Second

A general interval; the class of intervals between two notes whose named tones appear in consecutive order on the twelve-tone clock. A major second is two semitones in size and can be natural (e.g. C to D) or altered (e.g. B to C). A minor second is one semitone in size and can also be natural (e.g. B to C) or altered (e.g. C to D).

Of the seven natural seconds on the twelve-tone clock, five are major and two (E-F and B-C) are minor. Therefore the varieties of second which occur naturally are major and minor.

 

Semitone

The interval in pitch between any two adjacent tones. The ear perceives all semitones in common tunings as approximately equal intervals even though the frequency delta between adjacent notes varies logarithmically. From other sources you will hear the term half-step used to mean a semitone; I will not use that term.

 

Sharpen

When a note is sharpened, its pitch is raised by one semitone, thereby shifting it clockwise on the twelve-tone clock. Sharpening a flattened note moves it back counterclockwise towards the natural note.

 

Sound

Longitudinal waves which propagate through a medium such as air from an originating oscillator such as the vibrating parts of a musical instrument. Hearing is the subjective experience of sound and the human ear is sensitive to sound in a range of frequencies from about 20 Hz to about 20,000 Hz.

 

Third

A general interval; the class of intervals formed by two consecutive seconds. A major third is formed by two major seconds and is four semitones in size. Major thirds can be natural (e.g. C to E) or altered (e.g. B to D). A minor third is formed by a major second and a minor second in any order and is three semitones in size. A minor third can also be natural (e.g. B to C) or altered (e.g. C to D).

Of the seven natural thirds on the twelve-tone clock, three (C-E, F-A and G-B) are major and four are minor. Therefore the varieties of third which occur naturally are major and minor.

 

Tone

The term tone is overloaded with meaning. The Greek word tonos means tightening; that is, a taut string. This suggests that tone should mean the sound produced by such a string, so a reasonable definition for the word is as a synonym for pitch. But better than this is to limit tone to mean those pitches produced by a tuned musical instrument, and that is the sense in which I will use the word.

Tones are named by grouping them into sets of twelve (i.e. octaves) and repeating the names for successive sets of twelve. Seven of the twelve tones in an octave are named A-G and the remainder are unnamed. However, all tones have equal status whether named or not. It’s worth stressing that these are tone names and not note names. Tones are given names so that notes may be named in relation to them.

From some sources you will hear tone used in the sense of the combined interval of two adjacent semitones. You will also hear the term whole-step used to mean the same thing. Instead, for the sake of clarity, I will simply say two semitones. Neither will I use tone to mean timbre.

 

Twelve-Tone Clock

The twelve-tone clock is a visualization of the tones in a single octave. The pattern of the octave is repeated on musical instruments (tones of the same class in different octaves serve the same musical function) and between musical instruments, so this illustration focuses on the octave-in-general in an instrument-agnostic form.

Figure 1 - The Twelve-tone clock

Because the tones Figure 1 map right onto the hour positions of a clock, you can equate each of the tone positions with an hour position. The position of the C tone can be thought of as either 12 or 0 (midnight in the 24-hour system) as you prefer. You can also think of the angular distance between any two tones as a ‘time’ in five-minute units. Use the clock analogy as a tool to help you picture the twelve-tone clock as a mental image.

There is no particular starting-point on the twelve-tone clock, and nor does it need to be oriented with C at the 0 (or 12) position. You should aim, in time, to be able to visualize the circle rotated to any orientation.

 

Copyright (c) Steve White 2005

Author: "stevewhitepsfd" Tags: "Music theory, Voices, Pages"
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 08 Feb 2005 03:28

Follow this link and under Development you’ll see the job title Developer Consultant PSfD.

 

Tell them Steve sent you. :-)

 

Author: "stevewhitepsfd" Tags: "Software, General"
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 05 Feb 2005 23:07

Jason, thanks for your comment on the previous post. What particularly resonated with me was "Making it work for real would be a big deal where I work," because I'm part of Premier Support for Developers and our job is helping enterprise and ISV Microsoft customers with their app development issues. Customers buy an annual contract (there is a range of sizes) with my team and we work with them through the year so we get to know their systems.

I've just posted two articles under the Software category on the subject of SxS Managed COM - i.e. a native app activating an unregistered COM-Callable Wrapper which then delegates on to a managed class library. Generally the CCW would have to be registered but the SxS mechanism uses .manifest files to build in-memory structures known as Activation Contexts.

The two articles mention associated .zip files. I haven't included a link to these but there are clear steps in the articles (with source code and explanations) on how to produce the binaries for yourself. I hope these are of some use. Please note that the 'With Manifest File' article applies to Windows 2003 only and the 'With Manifest Resource' applies to both Windows 2003 and XP, so please choose the approach which fits your platform requirements.

 

Author: "stevewhitepsfd" Tags: "Software"
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 05 Feb 2005 17:51

This article is now superseded by the "Registration-Free Activation of .NET-Based Components: A Walkthrough" MSDN article. Please see the MSDNography links section.

Author: "stevewhitepsfd" Tags: "Software, Pages"
Comments Send by mail Print  Save  Delicious 
Next page
» You can also retrieve older items : Read
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader