News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

playcity - 6 channel sound (and 3 channel music and 3 channel sfx)

Started by arnoldemu, 09:45, 23 August 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

arnoldemu

I am a bit lazy and I hope somebody has made this already.

Is there an arkos player (or starkos) which has been adapted for 6 channel music for the playcity?

For a project I want to finish (which has been on hold for a few months) I have a need for 3 channel music and 3 channel sfx, does a player exist or do I need to make one and release it for others to use? (I will convert arkos player not make my own player).

I want to finish the project so I can concentrate on other more important projects but I want to support playcity with it.



My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

CraigsBar

There is both an adapted Arkos player and a 6 channel player on the Demo disc.


http://www.cpcwiki.eu/index.php/File:Playcity_examples.zip


If that is what you mean?


Craig
IRC:  #Retro4All on Freenode

arnoldemu

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Ast

happy you supported PlayCity. When will your project release ?
_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

arnoldemu

Quote from: Ast on 10:56, 23 August 14
happy you supported PlayCity. When will your project release ?
I will not give a date. Sorry.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Ast

_____________________

Ast/iMP4CT. "By the power of Grayskull, i've the power"

http://amstradplus.forumforever.com/index.php
http://impdos.wikidot.com/
http://impdraw.wikidot.com/

All friends are welcome !

Prodatron

Quote from: CraigsBar on 10:13, 23 August 14
There is both an adapted Arkos player and a 6 channel player on the Demo disc.
http://www.cpcwiki.eu/index.php/File:Playcity_examples.zip
Really impressive!
What kind of 6channel song formats are used or will be used? What do they use on the ZX? Is at a modified PT3 format?

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

arnoldemu

I talked with syx and what I need doesn't appear to be implemented yet. So I will try and implement it myself. I have two ideas of how to do this.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

TotO

The PlayCity embed 2 YMZ audio circuit.
- LEFT chip (3ch)
- RIGHT chip (3ch)

So, you can easily understand that no middle channel exist, and it should sound strange to use 3ch audio and 3ch sfx.
But... That open more interesting stereo things:

3ch twin:
- Sound left, middle, right with panning possibility and cut channels when sfx are played w/o loosing music.
It's the CPC extended way. You can use two Arkos tracker/player for that.

3+2ch:
- Using 1ch LEFT, "2ch twin" MIDDLE padding, 1ch RIGHT and 2ch for stereo sfx.
It's another CPC extended way. You can use two Arkos tracker/player for that.

4+2ch:
- Using 4ch for music and 2ch for stereo sfx.
It's the arcade way. Actually, you can use Vortex tracker/player to handle music.
You can use AyFxEdit (or Arkos Player) for SFX.

6ch:
- Using 6ch for music and cut channels when sfx are played.
It's the Megadrive way. Actually, you can use Vortex tracker/player to handle music.
You can use AyFxEdit (or Arkos Player) for SFX.

As you know, we are waiting a Work In Progress tracker and player that will fully support the PlayCity.
But actually, it is not finished... That is not an excuse to not make games!!!  :P
(the same occur on actual console. It's why, 2nd games generation are always more impressive than firsts...)
"You make one mistake in your life and the internet will never let you live it down" (Keith Goodyer)

arnoldemu

I did not know or I forgot there was a tracker in development.
I already have music and SFX made. This time I will use two arkos players for that.
My future plans will use other methods.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

SyX

Sorry, but it has been a really busy weekend.

The Arkos player in the PlayCity demos project, it comes from the first prototype board that only had one YMZ. Because that only let you choose which sound chip to use, the internal (PSG) or the external (YMZ). As i have another SFX player, i don't use the one in Arkos and because that it's not converted. And as i told you arnoldemu, if you need help adding it only tell me.

Quote from: Prodatron on 18:14, 23 August 14
What kind of 6channel song formats are used or will be used? What do they use on the ZX? Is at a modified PT3 format?
It's the standard Turbo Sound 6 channels format, that it's basically 2xPT3 songs. It's not the most optimized player, but people can use Vortex Tracker for making songs and have a little fun playing and trying things.

If everything goes well, we are going to have a really nice PlayCity tracker very soon :)

arnoldemu

@SyX : thank you for the offer. I am happy to look at the player and modify it. I don't know exactly how I want to use it yet. I will use your code as the base.

I use arkos for music and SFX this time.

I am also asking questions to think about plans for my other waiting projects.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

SyX

Well, i have cleaned and commented my SFX player (based in the ayFX player of Shiru) and i have attached to this post the sources and an example for PlayCity and PSG, and i will upload to the PlayCity wiki page.

The source of the player is:; ---------------------------------------------------------------------------
; SFX player (c) 2013 SyX
; Based in the Minimal ayFX player v0.15 by Shiru.
;
; Simply SFX player using one sound chip and the next channel selection
; priority:
; 1.- If we select the channel, the sound already playing is replaced by
; the new one.
;
; 2.- If the SFX is free to choose the channel and all the channels are
; busy, then it's choosen the channel that it has been more time sounding.
;
; Initialization:
; LD   A,Sound_Chip      ; (0 -> PSG | 1 -> Left YMZ | 2 -> Right YMZ)
; LD   HL,SFX_Bank_address
; CALL SFX_Init
;
; Send SFX to be played:
; LD   A,Channel_Number  ; (0 = Free | 1 = A | 2 = B | 3 = C)
; LD   L,SFX_Number      ; (0...255)
; CALL SFX_Send
;
; For playing the SFXs, you must call during the interrupt handler:
; CALL SFX_Play
; ---------------------------------------------------------------------------

; SFX Bank structure:
; -------------------
; 1.- Number of SFXs in the bank (1 byte)
; 2.- Table with the offsets to the SFX (2 bytes * SFX)
; 3.- SFXs

; SFX format:
; -----------
; We encode each interrupt (50Hz rate) with a sequence of bytes, the length of the
; sequence is variable and depends on the changes in the tone/noise/volume/channel.
;
; The format of bytes in the sequence is:
; %DN N P DC V3 V2 V1 V0
; V3-V0  -> New Volume
; DC = 1 -> Disable Channel
; P = 1  -> The next two bytes are the new period in that channel
; N = 1  -> The next byte is the new noise period
; DN = 1 -> Disable noise in that channel
;
; If P and N are 1, the period follows first and then the noise.
;
; The end SFX marker is the sequence $D0 (%11010000 Disable Channel, Disable Noise
; and get new noise period), $20 (%00100000 Noise period $20, no valid period).
;
; SFX_Channel_Buffer structure:
; -----------------------------
; 4 bytes for channel:
; 0-1 SFX current address (If high byte is 0, then the channel is free)
; 2-3 SFX playing time in frames

    ALIGN 4                     ; Align to an address 16 bytes multiple, for 8 bits INCs
SFX_Channel_Buffer
    DEFS 3 * 4

; ---------------------------------------------------------------------------
; Initialize SFX player.
; Turn off the channels and set the variables.
; ENTRIES:
;    HL = Bank SFX Address
;     A = 0 -> PSG | 1 -> Left YMZ | 2 -> Right YMZ
; ---------------------------------------------------------------------------
SFX_Init
    INC  HL                     ; Skip number of SFXs in the bank
   
    ; Save the pointer to the SFX offsets table
    LD   (SFX_Send.sm_sfx_bank_address + 1),HL

    ; Mark all channels as empty
    LD   HL,SFX_Channel_Buffer
    LD   DE,$00FF
    LD   B,12
.loop_clean_sfx_channel_buffer
    LD   (HL),D
    INC  L
    LD   (HL),D                 ; Channel Empty
    INC  L
    LD   (HL),E
    INC  L
    LD   (HL),E                 ; SFX playing time maximum
    INC  L
    DJNZ .loop_clean_sfx_channel_buffer

    ; Which sound chip need to be initialized?
    OR   A
    JR   Z,.initialize_psg
.initialize_ymzs
    ; --------------------------
    ; Initialization of the YMZs
    ; --------------------------
    DEC  A
    JR   NZ,.is_right_ymz
.is_left_ymz
    LD   HL,YMZ_SELECT_LEFT
    JR   .set_select_ymz
.is_right_ymz
    LD   HL,YMZ_SELECT_RIGHT
.set_select_ymz
    LD   (write_ymz.sm_ymz_select + 1),HL
   
    ; Initialize the YMZ registers
    LD   B,H
    LD   C,L
    LD   A,$D
.loop_init_ymz_registers
    OUT  (C),A                  ; Register
    DEC  B
    CP   7
    JR   NZ,.send_zero_ymz
    LD   A,$3F
    OUT  (C),A
    LD   A,6
    JR   .loop_init_ymz_registers
.send_zero_ymz   
    DEFB $ED,$71                ; OUT (C),0
    DEC  A
    JP   P,.loop_init_ymz_registers

    ; Patch the play routines for using the YMZ
    LD   HL,write_ymz
    LD   (SFX_Play.sm_write_psg_01 + 1),HL
    LD   (SFX_Play.sm_write_psg_02 + 1),HL
    LD   (SFX_Play.sm_write_psg_03 + 1),HL
    LD   (SFX_Play.sm_write_psg_04 + 1),HL
    LD   (SFX_Play.sm_write_psg_05 + 1),HL
   
    ; Reset the variable with the noise period (R6) and the mixers (R7)
    LD   HL,$3F00
    LD   (SFX_Play.sfx_noise_and_mixers + 1),HL
    RET

.initialize_psg
    ; -------------------------
    ; Initialization of the PSG
    ; -------------------------
    ; Set the PPI_A in output mode
    LD   BC,PPI_CONTROL + PPI_A_OUTPUT
    OUT  (C),C

    ; PSG Inactive (Needed in CPC+)
    DEC  B                      ; B = PPI_C
    DEFB $ED,$71                ; OUT (C),0

    ; Using write_psg
    LD   A,PSG_REG_0D
    LD   E,0
.loop_internal_ay
    CP   PSG_REG_07
    JR   NZ,.send_zero_psg
    LD   E,$FF
    JR   .send_byte
.send_zero_psg
    LD   E,0
.send_byte
    CALL write_psg
    DEC  A
    JP   P,.loop_internal_ay

    ; Patch routines for using the PSG
    LD   HL,write_psg
    LD   (SFX_Play.sm_write_psg_01 + 1),HL
    LD   (SFX_Play.sm_write_psg_02 + 1),HL
    LD   (SFX_Play.sm_write_psg_03 + 1),HL
    LD   (SFX_Play.sm_write_psg_04 + 1),HL
    LD   (SFX_Play.sm_write_psg_05 + 1),HL

    ; Reset the variable with the noise period (R6) and the mixers (R7)
    LD   HL,$FF00
    LD   (SFX_Play.sfx_noise_and_mixers + 1),HL
    RET

; ---------------------------------------------------------------------------
; Play the current frame of SFXs.
;
; The format of bytes in the sequence is:
; %DN N P DC V3 V2 V1 V0
; V3-V0  -> New Volume
; DC = 1 -> Disable Channel
; P = 1  -> The next two bytes are the new period in that channel
; N = 1  -> The next byte is the new noise period
; DN = 1 -> Disable noise in that channel
;
; If P and N are 1, the period follows first and then the noise.
;
; The end SFX marker is the sequence $D0 (%11010000 Disable Channel, disable Noise
; and get new noise period), $20 (%00100000 Noise period $20, no valid period).
;
; SFX_Channel_Buffer structure:
; -----------------------------
; 4 bytes for channel:
; 0-1 SFX current address (If high byte is 0, then the channel is free)
; 2-3 SFX playing time in frames
; ---------------------------------------------------------------------------
SFX_Play
    LD   BC,$03FD
    LD   IX,SFX_Channel_Buffer
.loop_sfx_play
    PUSH BC

    ; Check for END of SFX reached in a previous frame
    LD   A,11                   ; Envelope register 11 (first not used by the SFXs)
    LD   H,(IX + 1)             ; Comparison of byte address to <11
    CP   H
    JR   NC,.next_channel       ; Channel is not playing, skipping
    LD   L,(IX + 0)

    ; Get next SFX data byte
    LD   E,(HL)
    INC  HL

    ; Get channel volume register (A = 11, B = Channel processing)
    SUB  B                      ; A = Volume register | (8, 9, 10)

    ; Mask Volume
    LD   D,A

    LD   A,E
    AND  $0F
    LD   C,E                    ; Save E
    LD   E,A

    LD   A,D
   
    ; Send Volume
.sm_write_psg_01
    CALL $0000

    ; Check changes in tone period
    LD   E,C                    ; Restore E ***
    BIT  5,E                    ; Change the period of the tone?
    JR   Z,.not_change_period

    ; Get channel period tone register (D = Channel processing)
    LD   A,3
    SUB  D
    ADD  A,A                    ; A = Tone period register | (0, 2, 4)

    LD   E,(HL)
    INC  HL

    ; Send Fine Tune
.sm_write_psg_02
    CALL $0000

    ; Get coarse tune
    INC  A
    LD   E,(HL)
    INC  HL

    ; Send Coarse Tune
.sm_write_psg_03
    CALL $0000

    LD   E,C                    ; Restore E
.not_change_period

    ; Check changes in noise period
    BIT  6,E                    ; Change the period of the noise?
    JR   Z,.set_mixer_state

    LD   A,(HL)                 ; Read the value of the noise
    SUB  $20                    ; <$20, get the same lower 5 bits (Noise period)
    JR   C,.update_noise        ; Less than $20, play on
.stop_playing_sfx
    LD   H,A                    ; H = 0 (High byte 0 -> Channel Free)
    LD   B,$FF
    LD   B,C                    ; BC = $FFFF(Max. playing time)
    JR   .update_channel_buffer

.update_noise
    INC  HL
    LD   (SFX_Play.sfx_noise_and_mixers + 1),A

.set_mixer_state
    ; A = %01101111 | E = %DN N P DC V3 V2 V1 V0
    ; B = 3 : A %11110110 -> Enable noise and tone A : E %V3 V2 V1 V0 DN N P DC
    ; B = 2 : A %11101101 -> Enable noise and tone B : E %V2 V1 V0 DN N P DC V3
    ; B = 1 : A %11011011 -> Enable noise and tone C : E %V1 V0 DN N P DC V3 V2

    ; B is not changed, remain with the channel number
    INC  B                      ; Number of changes for flags TN
    LD   A,%01101111            ; Mask flags TN
.loop_get_mixer_mask_for_channel
    RRC  E
    RRCA
    DJNZ .loop_get_mixer_mask_for_channel

    ; Set Mixer state
    LD   D,A
    LD   BC,SFX_Play.sfx_noise_and_mixers + 2
    LD   A,(BC)
    XOR  E
    AND  D
    XOR  E
    LD   (BC),A

.increase_sfx_playing_time
    LD   C,(IX + 2)
    LD   B,(IX + 3)
    INC  BC

.update_channel_buffer
    LD   (IX + 2),C
    LD   (IX + 3),B             ; SFX playing time

    LD   (IX + 0),L
    LD   (IX + 1),H             ; SFX pointer

.next_channel
    LD   BC,4                   ; Go to the next channel
    ADD  IX,BC
    POP  BC
    DJNZ .loop_sfx_play

.sfx_noise_and_mixers
    LD   DE,0                   ; E = Noise period | D = Mixers
    LD   A,6
.sm_write_psg_04
    CALL $0000
    LD   E,D
    INC  A
.sm_write_psg_05
    JP   $0000

; ---------------------------------------------------------------------------
; Write a value in the PSG
; ENTRIES:
;    A = PSG Register
;    E = Value
;---------------------------------------------------------------------------                 
write_psg
    PUSH BC
    LD   B,>PPI_A
    OUT  (C),A                      ; Register
    LD   BC,PPI_C + PPI_PSG_SELECT
    OUT  (C),C
    DEFB $ED,$71                    ; OUT (C),0
    LD   B,>PPI_A
    OUT  (C),E                      ; Value
    LD   BC,PPI_C + PPI_PSG_WRITE
    OUT  (C),C
    DEFB $ED,$71                    ; OUT (C),0
    POP  BC
    RET

write_ymz
    PUSH BC
.sm_ymz_select
    LD   BC,$0000
    OUT  (C),A                  ; Register
    DEC  B
    OUT  (C),E                  ; Value
    POP  BC
    RET

; ---------------------------------------------------------------------------
; Send SFX to the channel selected or the first free channel.
;
; If we select the channel, the sound already playing is replaced by the
; new one.
;
; If the SFX is free to choose the channel and all the channels are busy,
; then it's choosen the channel that it has been more time sounding.
;
; ENTRIES:
;     A = Channel number (0 = Free | 1 = A | 2 = B | 3 = C)
;     L = SFX number (0...255)
; ---------------------------------------------------------------------------
SFX_Send
    ; Get the SFX address
    LD   H,0
    ADD  HL,HL
.sm_sfx_bank_address
    LD   BC,0                   ; SFX offsets table
    ADD  HL,BC
    LD   C,(HL)
    INC  HL
    LD   B,(HL)                 ; BC = Offset
    DEC  HL
    ADD  HL,BC                  ; HL = SFX address

    ; Get the channel
    OR   A
    JR   Z,.find_empty_channel
    DEC  A
    JR   NZ,.is_b_or_c
.is_a
    LD   DE,SFX_Channel_Buffer
    JR   .insert_sfx

.is_b_or_c
    DEC  A
    JR   NZ,.is_c
.is_b
    LD   DE,SFX_Channel_Buffer + 4
    JR   .insert_sfx

.is_c
    DEC  A
    LD   DE,SFX_Channel_Buffer + 4 * 2
   
    ; Insert SFX in the channel selected
.insert_sfx
    EX   DE,HL
    ; Set SFX pointer
    LD   (HL),E
    INC  L
    LD   (HL),D
    INC  L
    ; Initialize playing time
    LD   (HL),A
    INC  L
    LD   (HL),A
    RET

    ; Find a free channel for the new SFX
.find_empty_channel
    PUSH HL                     ; Save the SFX address
    LD   HL,SFX_Channel_Buffer
    LD   BC,0                   ; Init value for the search
    LD   IXL,3
.loop_find_empty_channel
    PUSH HL
    INC  L
    LD   A,(HL)
    OR   A
    JR   Z,.empty_channel       ; Empty channel?
    INC  L
    INC  L
    LD   A,B
    CP   (HL)
    JR   C,.select_channel_h

    JR   NZ,.next_channel
    DEC  L
    LD   A,C
    CP   (HL)
    JR   C,.select_channel_l
    INC  L
    JR   .next_channel
   
.select_channel_h
    DEC  L

.select_channel_l   
    LD   C,(HL)                 ; Update timing to the actual largest
    INC  L
    LD   B,(HL)
    POP  DE                     ; Update pointer to the selected channel
    JR   .skip_stack_pop

.next_channel
    POP  AF                     ; Skip old pointer to the channel
   
.skip_stack_pop   
    INC  L
    DEC  IXL
    JR   NZ,.loop_find_empty_channel
.end_loop_find_empty_channel
    POP  HL                     ; DE = Selected Channel Pointer | HL = SFX Pointer
    JR   .insert_sfx
.empty_channel
    POP  DE
    JR   .end_loop_find_empty_channel

The code works nice in my tests, it could have bugs and i'm sure it can be optimized a lot. All the code is free for using in any CPC projects(sorry C64 guys :P), and if somebody makes any improve, send me for everyone can benefit of your changes and appears in the credits.
.
.
.
This is one of those moments where i miss @Devilmarkus (he is really busy with his not CPC project those days), because the Shiru's tool for making those SFXs use the ZX frequencies, that is not a problem for the PlayCity but it's for the PSG. And Markus can make a java tool, more CPC friendly, in a few evenings.

TotO

"You make one mistake in your life and the internet will never let you live it down" (Keith Goodyer)

McKlain

Quote from: SyX on 15:41, 25 August 14If everything goes well, we are going to have a really nice PlayCity tracker very soon :)


How soon?  ;D

CraigsBar

Quote from: McKlain on 09:31, 26 August 14

How soon?  ;D
I was wondering if we were going to see some 6 channel tunes from McKlain. A 6 channel remix of the breaking baud soundtrack perhaps :-)
IRC:  #Retro4All on Freenode

McKlain


Prodatron

Quote from: SyX on 15:41, 25 August 14It's the standard Turbo Sound 6 channels format, that it's basically 2xPT3 songs. It's not the most optimized player, but people can use Vortex Tracker for making songs and have a little fun playing and trying things.
Ok, thanks, I got it! :)

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

SyX

Quote from: McKlain on 09:31, 26 August 14

How soon?  ;D
I don't know, in those cases is when is ready... but i already told him about abusing of you for beta testing, jajaja  ;D

TotO

You can start to do things with existing tools too. Someone tried Vortex Tracker 6 channels?
Waiting is never good for productivity!  ;D
"You make one mistake in your life and the internet will never let you live it down" (Keith Goodyer)

Prodatron

I will add 6channel PT3 support into SymAmp as soon as SymbOS 2.1 release is finished probably this weekend :P The solution with putting 2 modules into 1 file is quite funny but easy and functional :)

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

CraigsBar

Quote from: Prodatron on 19:44, 26 August 14
I will add 6channel PT3 support into SymAmp as soon as SymbOS 2.1 release is finished probably this weekend :P The solution with putting 2 modules into 1 file is quite funny but easy and functional :)
Yay a SymbOS update, Now that gets my interest. Other than 6 channel SymAmp, what otehr fixesor new bits can we expect?


Craig

IRC:  #Retro4All on Freenode

MacDeath

mostly a good pair of soundtrakkers, one on nAmstrad and another on modern PC and that's quite good enough...


otherwise, some routines library to use the other extra functionnalities of the PlayCity and implement those on a pair of popular existing emulators.

RockRiver

First Sorry!! if my words could sound like that I don't like the device. I will buy one (and the great idea MotherX4)
But after read your words I make some quick research about PT3 TurboSound files and I found that:


http://www.bitfellas.org/news.php?extend.1316.19
Wow!!! there is a YM chip 2203 ,  compatible with AY-3-8910and with FM. I think Syx told me about it in spanish CPC forums.

What about to implement two YM2203 instead of two YMZ294 it in PlayCity v2 ? 
YM2203 are very expensive? The logical and coding of the board will be too complicated? Maybe FM music is not the philosophy of the board?
But YM2203 is compatible with AY ... could sound like two AYs?

Well I search in forum about YM2203 while writing this post and I found that:
http://www.cpcwiki.eu/forum/amstrad-cpc-hardware/zx-spectrum-sound-card-transplantation-in-progress/

Then I wait cause they will be two different hardware projects... Maybe partners projects? Or rivals and I will buy the two sound boards then... might need to change my job as a musician to bank robber 8)
Let me say that I like standard music files intra- or inter- computer(retro) systems *.YM *.AYC *.PT3 (for 6 channels)...

Spectrum people (or MSX people in FM music) could feed our new and "hungry" CPC sound boards too.

TotO

In fact, you "don't like" because you think that is a sound board only...  ;) 

Understand that PlayCity allow to push the CPC by allowing to use its hidden features and made it better.
It was made to be CPC friendly, not to make it sounding or displaying like an other computer.
It was made to fit on a little board at a really low price to allow most peoples to get it. :)

I'm an arcade fan and I know all the Yamaha soundchip. I have tested a lot of them before making a choice.
Some chip that I have tested are far better than the old YM2203...

It's really easy to replay many channels using ADPCM and FM features... (like the NeoGeo chip) And after?
Don't forget that all those systems have a dedicated Z80 and RAM only for this usage.
If you add a big soundcard to the CPC, that will be only to replay tunes that are not from our computer.

Sorry, but it is definitivelly not interresting for peoples making games and utilites for the CPC.
It's just a smokescreen! (funny, but useless)  8)
"You make one mistake in your life and the internet will never let you live it down" (Keith Goodyer)

Powered by SMFPacks Menu Editor Mod