ym2149-common 0.8.0

Common traits and types for YM2149 chiptune replayers
Documentation
# ym2149-common

Shared traits, types, and utilities for YM2149 chiptune replayers.

## Overview

This crate provides the unified interface that all replayer crates (`ym2149-ym-replayer`, `ym2149-arkos-replayer`, `ym2149-ay-replayer`, `ym2149-sndh-replayer`) implement. It also provides shared utilities for register parsing, frequency calculations, and visualization.

**Key exports:**
- Player traits: `ChiptunePlayer`, `ChiptunePlayerBase`
- State types: `PlaybackState`, `ChannelStates`, `BasicMetadata`
- Register utilities: `channel_period`, `period_to_frequency`, `channel_frequencies`
- Constants: `PSG_MASTER_CLOCK_HZ`, `NOTE_NAMES`

## Key Types

### Trait Hierarchy

```
ChiptunePlayerBase (object-safe)
    └── ChiptunePlayer (adds metadata access)
```

### `ChiptunePlayerBase` trait

Object-safe base trait for playback operations. Use this when you need trait objects (`Box<dyn ChiptunePlayerBase>`):

```rust
use ym2149_common::{ChiptunePlayerBase, PlaybackState};

fn play_any(player: &mut dyn ChiptunePlayerBase) {
    player.play();

    // Generate audio samples
    let mut buffer = vec![0.0f32; 882]; // ~20ms at 44.1kHz
    player.generate_samples_into(&mut buffer);

    // Check playback state
    if player.state() == PlaybackState::Playing {
        println!("Playing audio...");
    }
}
```

### `ChiptunePlayer` trait

Extends `ChiptunePlayerBase` with metadata access. Use this when you need the specific metadata type:

```rust
use ym2149_common::{ChiptunePlayer, ChiptunePlayerBase, PlaybackState};

fn play_with_info<P: ChiptunePlayer>(player: &mut P) {
    player.play();

    // Generate audio samples (from ChiptunePlayerBase)
    let mut buffer = vec![0.0f32; 882];
    player.generate_samples_into(&mut buffer);

    // Access metadata (from ChiptunePlayer)
    if player.state() == PlaybackState::Playing {
        println!("Currently playing: {}", player.metadata().title());
    }
}
```

### `PlaybackMetadata` trait

Unified metadata access across all formats:

```rust
use ym2149_common::PlaybackMetadata;

fn show_info<M: PlaybackMetadata>(meta: &M) {
    println!("Title:  {}", meta.title());
    println!("Author: {}", meta.author());
    println!("Format: {}", meta.format());

    if let Some(frames) = meta.frame_count() {
        let duration = frames as f32 / meta.frame_rate() as f32;
        println!("Duration: {:.1}s", duration);
    }
}
```

### `PlaybackState` enum

Standard playback states used by all players:

```rust
use ym2149_common::PlaybackState;

match player.state() {
    PlaybackState::Stopped => println!("Stopped"),
    PlaybackState::Playing => println!("Playing"),
    PlaybackState::Paused  => println!("Paused"),
}
```

### `BasicMetadata` struct

A concrete metadata type for simple use cases:

```rust
use ym2149_common::BasicMetadata;

let meta = BasicMetadata {
    title: "My Song".into(),
    author: "Composer".into(),
    format: "YM".into(),
    frame_count: Some(5000),
    frame_rate: 50,
    ..Default::default()
};
```

## Usage

Add to your `Cargo.toml`:

```toml
[dependencies]
ym2149-common = "0.7"
```

All replayer crates re-export these types, so you typically don't need to depend on `ym2149-common` directly:

```rust
// These are equivalent:
use ym2149_common::{ChiptunePlayer, ChiptunePlayerBase};
use ym2149_ym_replayer::{ChiptunePlayer, ChiptunePlayerBase};
use ym2149_arkos_replayer::{ChiptunePlayer, ChiptunePlayerBase};
use ym2149_ay_replayer::{ChiptunePlayer, ChiptunePlayerBase};
use ym2149_sndh_replayer::{ChiptunePlayer, ChiptunePlayerBase};
```

## License

MIT