ひろばニュース|2026/06/19~2026/06/25号

今週のニュースです!新着などのお知らせだよ!
みかんの新着おんがく紹介①|フリーBGM『凱旋』

フリーBGM:凱旋(がいせん)
フリーBGM|ループ対応、用途:Youtube動画向け、ゲーム・アプリ向け、時間:2分41秒、BPM:116、キー:B♭m、ジャンル:あかるい、楽器:ストリングス|かっこいい凱旋をイメージした「逆転勝利!」をイメージした1曲です!エンディングで勝利の行進をするようなシーンにぴったり!

今週は1曲投稿しました!場面を豪華にしたいときはこのオーケストラ系素材を使ってみてください!
みかんの新着おんがく紹介②|今週の15秒&30秒BGMはこちら!

15秒フリーBGM:スペースオーケストラ(15秒 ver.)
フリーBGM|ループ対応、用途:Youtube動画向け、Shorts・Tiktok向け、ゲーム・アプリ向け、時間:0分15秒、BPM:174、キー:G#m、ジャンル:みらい、楽器:ストリングス、シンセサイザー|15秒BGM第55弾!近未来バトル風のオーケストラっぽい1曲です!ゲームのループBGMやSFっぽいシーンにぴったり!

30秒フリーBGM:冥府
フリーBGM|ループ対応、用途:Youtube動画向け、Shorts・Tiktok向け、ゲーム・アプリ向け、時間:0分30秒、BPM:63、キー:C#m、ジャンル:ゆったり、楽器:ピアノ、シンセサイザー|30秒BGM第38弾!かなり怖いシーンにぴったりの1曲です!冥界などのような絶望的なシーン、ホラー展開などにおすすめ!

今週も15秒&30秒BGMを追加しました!他にもあるのでぜひ見てみてください!
いろはの新着セットリスト|『洞窟』×『剣』

30秒フリーBGM:洞窟
フリーBGM|ループ対応、用途:Youtube動画向け、Shorts・Tiktok向け、ゲーム・アプリ向け、時間:0分30秒、BPM:111、キー:Bm、ジャンル:みらい、楽器:シンセサイザー|30秒BGM第32弾!洞窟での探検シーンや、TRPGでのダンジョンクエストの場面にぴったりのシンセサイザー系の一曲に仕上げました!

フリー効果音:剣
フリー効果音|ジャンル:かんきょう、バトルっぽい効果音!かっこいい剣の金属音です!

今週のセットリスト案のテーマは『ダンジョン』です。剣や魔法陣などで戦うRPGのシーンにぴったりですわね。
ことはの新着ソースコード|素材ページにて『フェードアウトON/OFF』を追加!
<div id="mikan-stem-app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lamejs/1.2.1/lame.all.min.js"></script>
<style>
.mikan-stem-container {
margin: 20px 0; padding: 15px;
background: #fffaf0; border-radius: 12px; border: 1px dashed #f39800;
}
.mikan-stem-label { font-size: 0.9rem; color: #666; margin-bottom: 10px; font-weight: bold; }
.mikan-stem-controls { display: flex; flex-wrap: wrap; gap: 10px; }
.stem-btn {
padding: 10px 18px; border: 2px solid #f39800; background: #fff; color: #f39800;
border-radius: 25px; cursor: pointer; font-weight: bold; transition: 0.3s; outline: none;
}
.stem-btn.active { background: #f39800; color: #fff; box-shadow: 0 4px 10px rgba(243, 152, 0, 0.3); }
#mikan-vol-slider { width: 100%; cursor: pointer; accent-color: #f39800; }
.download-button.processing { opacity: 0.7; pointer-events: none; filter: grayscale(0.5); }
.fade-btn {
padding: 10px 18px; border: 2px solid #f39800; background: #fff; color: #f39800;
border-radius: 25px; cursor: pointer; font-weight: bold; transition: 0.3s; outline: none; margin-left: auto;
}
.fade-btn.active { background: #e67e22; border-color: #e67e22; color: #fff; box-shadow: 0 4px 10px rgba(230, 126, 34, 0.3); }
.mikan-fade-wrapper { display: flex; justify-content: space-between; align-items: center; margin-top: 15px; }
</style>
<script>
const mikanConfig = {
artist: 'みかんのおんがくひろば',
album: 'みかんのおんがくひろば',
cover: 'https://mikanmusicsquare.com/wp-content/uploads/2025/10/bgmusic.png',
stems: [
{ id: 'full', label: 'Full Mix', url: '' },
{ id: 'melody', label: '伴奏のみ', url: '' },
{ id: 'back', label: 'パーカッションのみ', url: '' }
]
};
const mikanStem = {
main: null,
subAudios: {},
dlBtn: null,
fullUrl: "",
baseTitle: "",
currentDb: 0,
isFadeEnabled: false,
wasmModule: null,
async initWasm() {
try {
setTimeout(() => {
if (typeof Module !== 'undefined' && Module.asm) {
this.wasmModule = Module;
}
}, 1000);
} catch (e) {
}
},
build() {
const root = document.getElementById('mikan-stem-app');
if (!root) return;
let buttonsHtml = '';
let audiosHtml = '';
mikanConfig.stems.forEach((stem, index) => {
const activeClass = index === 0 ? 'active' : '';
buttonsHtml += `<button type="button" onclick="mikanStem.toggle('${stem.id}', this)" class="stem-btn ${activeClass}">${stem.label}</button>`;
if (stem.url) {
audiosHtml += `<audio id="stem-audio-${stem.id}" src="${stem.url}" preload="auto" style="display:none;"></audio>`;
}
});
root.innerHTML = `
<div class="mikan-stem-container">
<div class="mikan-stem-label"><i class="fas fa-sliders-h"></i> 音源切り替え</div>
<div class="mikan-stem-controls">
${buttonsHtml}
<button type="button" id="mikan-fade-toggle" onclick="mikanStem.toggleFade(this)" class="fade-btn">
フェードアウト:OFF
</button>
</div>
<hr style="border: 0; border-top: 1px dashed #f39800; margin: 20px 0; opacity: 0.3;">
<div class="mikan-stem-label" style="margin-bottom: 10px;"><i class="fas fa-volume-down"></i> ダウンロード音量(dB)</div>
<input type="range" id="mikan-vol-slider" min="-30" max="0" step="0.5" value="0">
<div style="text-align: center; margin-top: 10px; font-weight: bold; color: #f39800;">
<span id="mikan-db-display">0.0</span> dB
</div>
</div>
${audiosHtml}
`;
},
init() {
this.build();
this.initWasm();
this.dlBtn = document.querySelector('.download-button');
this.main = document.querySelector('.wp-audio-shortcode audio, .wp-block-audio audio');
if (!this.main) return;
const titleElement = document.querySelector('.entry-title, .wp-block-post-title');
this.baseTitle = titleElement ? titleElement.innerText.replace(/.*フリーBGM\s*[::]\s*/, '').trim() : '名称未設定';
this.fullUrl = this.main.src;
mikanConfig.stems.forEach(stem => {
if (stem.url) {
const el = document.getElementById(`stem-audio-${stem.id}`);
this.subAudios[stem.id] = el;
el.muted = true;
}
});
const slider = document.getElementById('mikan-vol-slider');
const display = document.getElementById('mikan-db-display');
slider.addEventListener('input', (e) => {
this.currentDb = parseFloat(e.target.value);
display.innerText = this.currentDb.toFixed(1);
const ratio = Math.pow(10, this.currentDb / 20);
this.main.volume = ratio;
Object.values(this.subAudios).forEach(s => s.volume = ratio);
});
if (this.dlBtn) {
this.dlBtn.addEventListener('click', (e) => {
e.preventDefault();
this.processDownload();
});
}
const allSubs = Object.values(this.subAudios);
this.main.addEventListener('play', () => {
allSubs.forEach(s => { s.currentTime = this.main.currentTime; s.play(); });
});
this.main.addEventListener('pause', () => allSubs.forEach(s => s.pause()));
this.main.addEventListener('seeking', () => allSubs.forEach(s => s.currentTime = this.main.currentTime));
},
toggleFade(btn) {
this.isFadeEnabled = !this.isFadeEnabled;
if (this.isFadeEnabled) {
btn.classList.add('active');
btn.innerHTML = 'フェードアウト:ON';
} else {
btn.classList.remove('active');
btn.innerHTML = 'フェードアウト:OFF';
}
},
toggle(id, btn) {
if (!this.main) return;
this.main.muted = true;
Object.values(this.subAudios).forEach(s => s.muted = true);
let targetUrl = this.fullUrl;
if (id === 'full') {
this.main.muted = false;
} else if (this.subAudios[id]) {
this.subAudios[id].muted = false;
targetUrl = this.subAudios[id].src;
}
if (this.dlBtn) this.dlBtn.href = targetUrl;
document.querySelectorAll('.stem-btn').forEach(b => b.classList.remove('active'));
if (btn) btn.classList.add('active');
},
async processDownload() {
if (!this.dlBtn) return;
const originalHtml = this.dlBtn.innerHTML;
const url = this.dlBtn.href || this.fullUrl;
try {
this.dlBtn.classList.add('processing');
this.dlBtn.innerHTML = '<i class="fas fa-cog fa-spin"></i> 生成中...';
const ctx = new (window.AudioContext || window.webkitAudioContext)();
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
const gain = Math.pow(10, this.currentDb / 20);
const numChannels = audioBuffer.numberOfChannels;
const sampleRate = audioBuffer.sampleRate;
const duration = audioBuffer.duration;
const length = audioBuffer.length;
const mp3encoder = new lamejs.Mp3Encoder(numChannels, sampleRate, 192);
const mp3Data = [];
let samplesL = audioBuffer.getChannelData(0);
let samplesR = numChannels > 1 ? audioBuffer.getChannelData(1) : samplesL;
if (this.wasmModule) {
const bytesPerSample = 4;
const ptrL = this.wasmModule._malloc(length * bytesPerSample);
const ptrR = this.wasmModule._malloc(length * bytesPerSample);
this.wasmModule.HEAPF32.set(samplesL, ptrL / bytesPerSample);
this.wasmModule.HEAPF32.set(samplesR, ptrR / bytesPerSample);
const fadeTargetTime = this.isFadeEnabled ? duration : (duration + 9999.0);
this.wasmModule._apply_fade_and_gain(ptrL, length, sampleRate, fadeTargetTime, gain);
if (numChannels > 1) {
this.wasmModule._apply_fade_and_gain(ptrR, length, sampleRate, fadeTargetTime, gain);
}
samplesL = new Float32Array(this.wasmModule.HEAPF32.buffer, ptrL, length);
samplesR = numChannels > 1 ? new Float32Array(this.wasmModule.HEAPF32.buffer, ptrR, length) : samplesL;
setTimeout(() => {
this.wasmModule._free(ptrL); this.wasmModule._free(ptrR);
}, 100);
} else {
const fadeDurationSamples = sampleRate;
const endSampleIdx = samplesL.length;
const startFadeIdx = endSampleIdx - fadeDurationSamples;
for (let i = 0; i < endSampleIdx; i++) {
let currentGain = gain;
if (this.isFadeEnabled) {
if (i >= startFadeIdx) {
let progress = (i - startFadeIdx) / fadeDurationSamples;
currentGain *= (1.0 - progress);
}
}
samplesL[i] = samplesL[i] * currentGain;
if (numChannels > 1) {
samplesR[i] = samplesR[i] * currentGain;
}
}
}
const block = 1152;
for (let i = 0; i < samplesL.length; i += block) {
const leftChunk = new Int16Array(block);
const rightChunk = new Int16Array(block);
for (let j = 0; j < block; j++) {
if (i + j < samplesL.length) {
leftChunk[j] = samplesL[i + j] * 32767;
rightChunk[j] = samplesR[i + j] * 32767;
}
}
const mp3buf = mp3encoder.encodeBuffer(leftChunk, rightChunk);
if (mp3buf.length > 0) mp3Data.push(mp3buf);
}
const end = mp3encoder.flush();
if (end.length > 0) mp3Data.push(end);
const blob = new Blob(mp3Data, { type: 'audio/mp3' });
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
let baseName = url.split('/').pop().split('?')[0].replace('.mp3', '');
const dbSuffix = (this.currentDb === 0) ? "" : `_${this.currentDb}dB`;
const fadeSuffix = this.isFadeEnabled ? "_fadeout" : "";
a.download = `${baseName}${dbSuffix}${fadeSuffix}.mp3`;
a.click();
URL.revokeObjectURL(downloadUrl);
} catch (e) {
console.error(e);
alert("MP3生成またはフェード処理に失敗しました。");
} finally {
this.dlBtn.classList.remove('processing');
this.dlBtn.innerHTML = originalHtml;
}
}
};
window.addEventListener('load', () => mikanStem.init());
</script>
おんがく素材ページにて、素材の再生終了時間1~2秒前から『フェードアウト』処理を自動でつけるかどうかの切り替えボタンを配置しました。ぜひ一読ください。


