ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Swan's Quest 第4章:シークエンスの完了
Swift Playgroundsはすべての世代に向けて4章から成るインタラクティブな冒険、"Swan's Quest"をお届けします。いよいよグランドフィナーレへと向かいます。あなたは身に着けたスキルを音で磨きをかけてきました。ただしこの章では、ヒーローは複数のパートから成るハーモニーをシークエンスしなくてはなりません。 MIDIコードを使い、音程を持つ楽器を演奏する方法を見つけましょう。そうすればあなたは、ヒーローがリズムを見つけ・・・そして、クエストが攻略する手助けができるかもしれません。 Swan's QuestはiPadとMacのSwift Playgroundsのために作成されており、Sonic Workshop、Sensor Arcade、Augmented RealityなどのPlaygroundsの多くで教育的体験を生むフレームワークとリソースを統合しています。Playgroundを作成するには、"Create Swift Playgrounds content for iPad and Mac"をご覧ください。 Developer Forumに立ち寄るのも忘れずに。Swan's Questへのご意見をぜひお聞かせください。
リソース
関連ビデオ
WWDC20
-
ダウンロード
こんにちは WWDCへようこそ “Swan's Quest 第4章:シークエンスの完了” Swan's Questへようこそ 司会のロブです クエストの最後のチャプターの 内側をご案内します ここまでは お楽しみいただけましたか 最後のチャプターでは ToneOutputから離れて― 楽器のサンプリングについて ご説明します このチャプターは トカゲに会える最後のチャンスです スワンの宝箱は謎のまま… 見てからのお楽しみです 今回のチャレンジで 重要な役割を果たすのは― シーケンサー とだけ言っておきましょう まずは シーケンサーの入門から そしてSwiftで構築するための いくつかのヒントがあります スティーブンが再び コンテンツSDKのAPIを説明してくれます サンプリングされた楽器の演奏と― SDKで提供される楽器の ライブラリの概要の説明です また GarageBandでサンプリングした方法も 教えてくれますよ そして 最後のサイドクエストで まとめます 名残惜しいですね ステップシーケンサーについて ご説明しましょう 3回目のチャレンジの最後で― スワンからもらった巻物には 2つのパートがありました すごいよ スワン 前回のチャレンジと違って― 複数の楽器を同時に 演奏しなければなりません 複数のパートを 同時に演奏するために― ステップシーケンサーの 構築方法をご説明します 驚くべきことに― このシーケンサーに必要なタイマーは 1つだけです ToneOutputの代わりに 利用するのは― コンテンツSDKに含まれる サンプリングされた楽器です シーケンサーは 複数トラックの タイミングループです 等しいチャンク あるいは ステップに分割されていて― あらかじめ定義された長さを 順番に演奏します それぞれのトラックは ピッチ付きの楽器のインスタンスです また シーケンサーは パーカッションのような ピッチなしの楽器も使用します
とても汎用的ですよね 背景の雰囲気を出すループを 作るのにもってこいです それに メロディを伴奏する ドラムのビートも ステップシーケンサーでは 複数のトラックを重ねてレイヤ化できます ここに示す例では― 管楽器のトラック ギターのトラック パーカッションのトラックがあります このシーケンスの各カラムは 4分音符分の長さです これは8ビート つまり4/4拍子の2小節です または 音楽用語では “コモンタイム”と言います
シーケンサーのタイミングループの 例を見てみましょう タイマーのインターバルの 決め方は― 全体の長さである4秒を ビート数 つまり― このシーケンスでは 8で分割します トラックとコードを追加して 各トラックの中の楽器を演奏します スティーブンと一緒に やってみましょう ありがとう ロブ コンテンツSDKには豊富なAPIと― 楽器のライブラリを 用意しておきました まず “Sensor Arcade”に Instruments APIを導入し― “Sensor Create”という テンプレートを含めました 自分で音楽を書くことができます そして昨年“Sonic Workshop”と― その入門編として “Sonic Create”をリリースしました どちらにも 7種類の楽器のサンプルが 3オクターブ分入っています 基本となるAPIは playInstrumentメソッドです このAPIでは 7種類の楽器のうち どれか1つを参照する必要があります PlaygroundsのコンテンツSDKに 含まれる楽器 つまり― エレキギター ベースギター ピアノ ウォームベル セブンシンセ ベースシンセ そして クリスタルシンセです playInstrumentメソッドに必要な もう1つの項目は― MIDINoteProtocolの値です MIDI音には8ビットの 整数値が含まれます これらは 適切なMIDIコードに 対応しています こちらの実装例は 第2オクターブの エンコードされたMIDI音です ここに restという値を 含めています これは シーケンスの中で 楽器を無音にすることを表します
コードを更新する前に トラックについてお話しします Sequencer.Swiftには TrackProtocolという プロトコルも含めておきました これには 楽器の値 トラックの長さ そして― シーケンス内の任意のステップの MIDI音を提供するメソッドが含まれます 実装例はこのようになります 音のプロパティの有無をチェックするように そしてインデックス付きの― ステップがシーケンスの境界を 超えないように注意してください すべての要素が揃いましたので 基本のコードに戻りましょう まず 2つのトラックを作ります ベースとピアノです これらを組み合わせて配列にします 作成できたら それぞれのトラックに 音のパターンを割り当てます 最後に 選択したトラックを ループして― 割り当てられた楽器の 音を演奏します シーケンスが一巡したところで 必ずendPerformanceメソッドを 呼んでください 答えの確信が得られます では コードを更新しましょう シーケンスのループが完了すると インデックスを再利用します インデックスを0にリセットした後 endPerformanceを呼び出します それで チャレンジを完成させたことが スワンに伝わります 次に GarageBandでの サンプリングについてご説明します 楽器を自作する方法の1つが― GarageBandから自分のサンプルを 作成することです まず GarageBandを開き “キーボード”を選択します または サンプリングしたい 別の楽器でも構いません キーボードの中には たくさんの楽器のオプションがあります ここでは 日本の伝統楽器 “琴”を選択しました 他にも たくさんの楽器の プロパティを変更できます トーンやレゾナンスなどです
キーボードで使用する スケールも選べます 演奏したい音を出すのが ずっと簡単になります ここでは メジャースケールを 選択します
個々の音を録音したら― 再生して 期待どおりの音に なっているか確認します
必要ならば GarageBandエディタで 修正してから― 書き出します 準備ができたら 曲を書き出します 最もロスが少ないフォーマットは 非圧縮WAVですが― 圧縮フォーマットでも 書き出すことができます 書き出したら 個々の音をトリムして― プロジェクトに読み込み 自分の楽器を作成します ロブ ここで最後の サイドクエストをやらないとね そうだね スティーブン 皆さん 準備はいいですか? 大丈夫?
今回はネタバレなしです この最後のサイドクエストでは これまでの― 4つのチャプターで学んだすべてを 組み合わせます ToneOutputを楽器として ステップシーケンサーに追加します 今回のエピソードでは Swan's Questの最終チャレンジを― 達成するヒントについて ご説明しました ステップシーケンサーの基本と― 複数パートのハーモニーを 作成するための使い方を学びました Swift Playgroundsに含まれている あらかじめサンプリングされた楽器の紹介と 自分の楽器をサンプリングして 作成する方法を お教えしました Swan's Questをお楽しみいただき Swift Playgroundsと― 埋め込みコンテンツSDKで できることを 学んでいただけますと幸いです 復習が必要な時 または もう一度やってみたい時は 前回までのエピソードを チェックしてください 幸運を祈ります そしてぜひ― フォーラムに参加して 皆さんの サイドクエストの答えを共有してください お待ちしています
-
-
2:26 - Barebones example of a sequencer
// A barebones example of a sequencer let numberOfBeats = 8 // two bars of 4/4 let duration = 4.0 // seconds let interval = duration / Double(numberOfBeats) var index = 0 Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in // Play each track's Instrument // ... index = (index + 1 < numberOfBeats) ? index + 1 : 0 }
-
3:16 - Introduction to playInstrument(_:note:volume:)
// Sequencer.swift func playInstrument(_ kind: Instrument.Kind, note: MIDINoteProtocol, volume: Double = 75) // Instrument.swift public class Instrument { /// The kind of included instruments public enum Kind: String { case electricGuitar, bassGuitar, piano, warmBells, sevenSynth, bassSynth, crystalSynth } // ... }
-
3:38 - MIDINoteProtocol
// Sequencer.swift protocol MIDINoteProtocol { /// note as an 8-bit MIDI code var midiCode: UInt8 { get } }
-
3:48 - Example implementation for Notes
// Example implementation for Notes enum MIDINotes: UInt8, MIDINoteProtocol { case rest = 0 case C2 = 36 case D2 = 38 case E2 = 40 case F2 = 41 case G2 = 43 case A2 = 45 case B2 = 47 var midiCode: UInt8 { return self.rawValue } }
-
4:03 - TrackProtocol
// Sequencer.swift protocol TrackProtocol { associatedtype NoteType : MidiNoteProtocol /// The kind of instrument that the track sequences var instrument: Instrument.Kind { get } /// Number of beats contained in the sequence var length: Int { get } /// MIDI code for the sequence frame func note(for frame: Int) -> NoteType }
-
4:21 - Example implementation for Tracks
// Example implementation for Tracks struct Track : TrackProtocol { var instrument: Instrument.Kind var length: Int var notes: [MIDINotes]? = nil func note(for frame: Int) -> MIDINotes { guard let n = notes, frame < n.count else { return .rest } return n[frame] } }
-
4:34 - Implementing a Sequencer
// A barebones example of a sequencer let numberOfBeats = 8 // two bars of 4/4 let duration = 4.0 // seconds var bass = Track(instrument: .bassGuitar, length: numberOfBeats) var piano = Track(instrument: .piano, length: numberOfBeats) let tracks = [bass, piano] bass.notes = [.rest, .C2, .A2, .rest, .C2, .A2, .D2, .C2 ] piano.notes = [.A2, .A2, .C2, .F2, .A2, .C2, .none, .F2] let interval = duration / Double(numberOfBeats) var index = 0 Timer.scheduledTimer(withTimeInterval: interval, repeats: true, block: { timer in for track in tracks { playInstrument(track.instrument, note: track.note(for: index)) } index = (index + 1 < numberOfBeats) ? index + 1 : 0 })
-
5:00 - // Getting credit for our work
// Getting credit for our work Timer.scheduledTimer(withTimeInterval: interval, repeats: true, block: { timer in for track in tracks { playInstrument(track.instrument, note: track.note(for: index)) } if index + 1 < numberOfBeats { index = index + 1 } else { index = 0 owner.endPerformance() } })
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。